diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml index b7018a5fc95d4149e562979756df2497446b04bb..93dd4e4b9f08333a89f8e5a36a63ff4dc1afb9b4 100644 --- a/.github/workflows/submit.yml +++ b/.github/workflows/submit.yml @@ -23,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 }} @@ -70,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' @@ -125,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 }}" @@ -253,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 }}" @@ -435,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 }}" @@ -582,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 }}" @@ -718,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 }}" @@ -869,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 }}" @@ -957,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 }}" @@ -1108,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 }}" @@ -1283,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 }}" @@ -1384,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 }}" @@ -1514,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 cbc7edd7e105e473b6c3e5f1e8033d85e570896e..4745af2a1d748fa6d8fb3f9856f8eab235a72002 100644 --- a/doc/building.html +++ b/doc/building.html @@ -273,7 +273,7 @@ Linux -gcc 10.2.0 +gcc 11.2.0 macOS @@ -281,14 +281,14 @@ Windows -Microsoft Visual Studio 2019 update 16.7.2 +Microsoft Visual Studio 2022 update 17.1.0

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.

@@ -890,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 f71e4e2e7302c76f0dc19988f97be7048e09de82..f3b0ee10522ab540287a0bf582cf10edd93015b3 100644 --- a/doc/building.md +++ b/doc/building.md @@ -329,9 +329,9 @@ 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 + Windows Microsoft Visual Studio 2022 update 17.1.0 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 @@ -343,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. @@ -1527,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: + +``` +export SOURCE_DATE_EPOCH=946684800 +bash configure --with-version-opt=adhoc +make +``` -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. +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. - * Do not rely on `configure`'s default adhoc version strings +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: -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=`. + * `--with-source-date` - * Specify how the build sets `SOURCE_DATE_EPOCH` + 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 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`. + 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. -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. + 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`. -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. + * `--with-hotspot-build-time` -**Hint:** If your build environment already sets `SOURCE_DATE_EPOCH`, you can -propagate this using `--with-source-date=$SOURCE_DATE_EPOCH`. + 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..f0dfad09eb8f76153a30b3926a85b5d8a6cb2f2c 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -51,6 +51,7 @@
  • <atomic>
  • Uniform Initialization
  • Local Function Objects
  • +
  • Inheriting constructors
  • Additional Permitted Features
  • Excluded Features
  • Undecided Features
  • @@ -68,7 +69,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 +154,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 +211,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 +271,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.

      @@ -405,6 +406,10 @@ while ( test_foo(args...) ) { // No, excess spaces around control
    • Make () more optional for lambdas (p1102r2)
    +

    Inheriting constructors

    +

    Do not use inheriting constructors (n2540).

    +

    C++11 provides simple syntax allowing a class to inherit the constructors of a base class. Unfortunately there are a number of problems with the original specification, and C++17 contains significant revisions (p0136r1 opens with a list of 8 Core Issues). Since HotSpot doesn't support use of C++17, use of inherited constructors could run into those problems. Such uses might also change behavior in a future HotSpot update to use C++17 or later, potentially in subtle ways that could lead to hard to diagnose problems. Because of this, HotSpot code must not use inherited constructors.

    +

    Note that gcc7 provides the -fnew-inheriting-ctors option to use the p0136r1 semantics. This is enabled by default when using C++17 or later. It is also enabled by default for fabi-version=11 (introduced by gcc7) or higher when using C++11/14, as the change is considered a Defect Report that applies to those versions. Earlier versions of gcc don't have that option, and other supported compilers may not have anything similar.

    Additional Permitted Features

    • constexpr (n2235) (n3652)

    • @@ -423,6 +428,7 @@ while ( test_foo(args...) ) { // No, excess spaces around control

      final virtual specifiers for classes and virtual functions (n2928), (n3206), (n3272)

    • override virtual specifiers for virtual functions (n2928), (n3206), (n3272)

    • Range-based for loops (n2930) (range-for)

    • +
    • Unrestricted Unions (n2544)

    Excluded Features

      @@ -438,7 +444,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..9dfff6f3ff1244e2d11dd7b5993b51d683d35f64 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 @@ -975,10 +985,34 @@ References from C++23 [p1102r2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1102r2.html +### Inheriting constructors + +Do not use _inheriting constructors_ +([n2540](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm)). + +C++11 provides simple syntax allowing a class to inherit the constructors of a +base class. Unfortunately there are a number of problems with the original +specification, and C++17 contains significant revisions ([p0136r1] opens with +a list of 8 Core Issues). Since HotSpot doesn't support use of C++17, use of +inherited constructors could run into those problems. Such uses might also +change behavior in a future HotSpot update to use C++17 or later, potentially +in subtle ways that could lead to hard to diagnose problems. Because of this, +HotSpot code must not use inherited constructors. + +Note that gcc7 provides the `-fnew-inheriting-ctors` option to use the +[p0136r1] semantics. This is enabled by default when using C++17 or later. +It is also enabled by default for `fabi-version=11` (introduced by gcc7) or +higher when using C++11/14, as the change is considered a Defect Report that +applies to those versions. Earlier versions of gcc don't have that option, +and other supported compilers may not have anything similar. + +[p0136r1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html + "p0136r1" + ### 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 @@ -1033,6 +1067,9 @@ References from C++23 ([n2930](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html)) ([range-for](https://en.cppreference.com/w/cpp/language/range-for)) +* Unrestricted Unions +([n2544](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf)) + ### Excluded Features * New string and character literals @@ -1064,7 +1101,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 +1122,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 +1143,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/Doctor.gmk b/make/Doctor.gmk new file mode 100644 index 0000000000000000000000000000000000000000..3acbb4aa38d801bbab81451a653d053d09d7dfe7 --- /dev/null +++ b/make/Doctor.gmk @@ -0,0 +1,148 @@ +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, Doctor.gmk)) + +################################################################################ +# +# Help user diagnose possible errors and problems with the build environment. +# + +prologue: + $(ECHO) + $(ECHO) '"make doctor" will help you analyze your build environment. It can highlight' + $(ECHO) 'certain well-known problems, but it can never find all possible errors.' + +TARGETS += prologue + +check-git: prologue + $(ECHO) + $(ECHO) '* Verifying that configure has picked up git...' + ifeq ($(GIT), ) + $(ECHO) 'WARNING: "git" is not present. This will disable several checks.' + $(ECHO) '! Correct by installing git and verifying that it is in the PATH' + endif + +TARGETS += check-git + +ifneq ($(GIT), ) + AUTOCRLF := $(shell $(GIT) config core.autocrlf) +endif + +check-autocrlf: check-git + ifneq ($(GIT), ) + ifeq ($(call isBuildOs, windows), true) + $(ECHO) + $(ECHO) '* Verifying git core.autocrlf value...' + ifneq ($(AUTOCRLF), false) + $(ECHO) 'WARNING: core.autocrlf is not "false". HIGH RISK of build failure!' + $(ECHO) '! Correct by running 'git config --global core.autocrlf false' and re-cloning the repo' + endif + endif + endif + +TARGETS += check-autocrlf + +check-configure-warnings: check-autocrlf + $(ECHO) + $(ECHO) '* Checking for warnings from configure...' + warning_output=`$(GREP) -e "^\* Memory limit:" -A 300 $(OUTPUTDIR)/configure.log | $(TAIL) -n +3 | $(SED) -e '$(DOLLAR){/^$(DOLLAR)/d;}'` && \ + if test -n "$$warning_output" ; then \ + $(ECHO) ' ---' ; \ + $(GREP) -e "^\* Memory limit:" -A 300 $(OUTPUTDIR)/configure.log | $(TAIL) -n +3 | $(SED) -e '$(DOLLAR){/^$(DOLLAR)/d;}' ; \ + $(ECHO) ' ---' ; \ + $(ECHO) '! Inspect the warnings, fix any problems, and re-run configure' ; \ + fi + +TARGETS += check-configure-warnings + +ifneq ($(GIT), ) + # This might have been set by custom component + UNTRACKED_FILES ?= $(shell $(GIT) status --porcelain --ignored | $(CUT) -c 4-) +endif + +check-core-files: check-configure-warnings + ifneq ($(GIT), ) + $(ECHO) + $(ECHO) '* Checking for left-over core files...' + core_files_found=`echo "$(UNTRACKED_FILES)" | $(TR) ' ' '\n' | $(GREP) core` && \ + if test -n "$$core_files_found" ; then \ + $(ECHO) 'Found these potential core files. They might interfere with the build process:' ; \ + $(ECHO) ' ---' ; \ + $(ECHO) $$core_files_found | $(TR) ' ' '\n'; \ + $(ECHO) ' ---' ; \ + $(ECHO) '! Remove left-over core files' ; \ + fi || : # do nothing if grep returns non-0 value + endif + +TARGETS += check-core-files + +check-bad-file-names: check-core-files + ifneq ($(GIT), ) + $(ECHO) + $(ECHO) '* Checking for untracked files with illegal names...' + core_files_found=`echo "$(UNTRACKED_FILES)" | $(TR) ' ' '\n' | $(GREP) '#'` && \ + if test -n "$$core_files_found" ; then \ + $(ECHO) 'Found these files with illegal names. They *will* cause build failures:' ; \ + $(ECHO) ' ---' ; \ + $(ECHO) $$core_files_found | $(TR) ' ' '\n'; \ + $(ECHO) ' ---' ; \ + $(ECHO) '! Remove all files with '#' in their name from the JDK source tree' ; \ + fi || : # do nothing if grep returns non-0 value + endif + +TARGETS += check-bad-file-names + +epilogue: check-bad-file-names + $(ECHO) + $(ECHO) '* If all else fails, try removing the entire build directory and re-creating' + $(ECHO) 'the same configuration using:' + $(ECHO) ' ---' ; \ + $(ECHO) configure_command_line=\$$\(make print-configuration\) + $(ECHO) make dist-clean + $(ECHO) bash configure \$$configure_command_line + $(ECHO) ' ---' ; \ + $(ECHO) + $(ECHO) '* The build README (doc/building.md) is a great source of information,' + $(ECHO) 'especially the chapter "Fixing Unexpected Build Failures". Check it out!' + $(ECHO) + $(ECHO) '* If you still need assistance please contact build-dev@openjdk.java.net.' + $(ECHO) + +TARGETS += epilogue + +################################################################################ + +doctor: $(TARGETS) + +all: doctor + +.PHONY: default all doctor $(TARGETS) diff --git a/make/Global.gmk b/make/Global.gmk index f9200d168517816b18f91671f73835765a5d5822..618e9ca243993a8b6e818d88fd661abb3a1c64c1 100644 --- a/make/Global.gmk +++ b/make/Global.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 @@ -53,14 +53,17 @@ help: $(info $(_) make docs-jdk-api # Create just JDK javadocs) $(info $(_) make bootcycle-images # Build images twice, second time with newly built JDK) $(info $(_) make install # Install the generated images locally) - $(info $(_) make reconfigure # Rerun configure with the same arguments as last time) - $(info $(_) make help # Give some help on using make) $(info $(_) make check # Run basic testing (currently tier1)) $(info $(_) make test- # Run test, e.g. test-tier1) $(info $(_) make test TEST= # Run test(s) given by TEST specification) $(info $(_) make exploded-test TEST= # Run test(s) on the exploded image instead of) $(info $(_) # the full jdk image) $(info ) + $(info Targets for troubleshooting) + $(info $(_) make help # Give some help on using make) + $(info $(_) make doctor # Diagnose build environment problems) + $(info $(_) make reconfigure # Rerun configure with the same arguments as last time) + $(info ) $(info Targets for cleaning) $(info $(_) make clean # Remove all files generated by make, but not those) $(info $(_) # generated by configure) diff --git a/make/Init.gmk b/make/Init.gmk index 4d297ee85e9e51e6d56b84aae2925af1548333b1..d20ea3b6f057363302260c14f010072df93cb50c 100644 --- a/make/Init.gmk +++ b/make/Init.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 @@ -352,7 +352,7 @@ else # HAS_SPEC=true $(call PrintFailureReports) $(call PrintBuildLogFailures) $(call ReportProfileTimes) - $(PRINTF) "Hint: See doc/building.html#troubleshooting for assistance.\n\n" + $(PRINTF) "HELP: Run 'make doctor' to diagnose build problems.\n\n" ifneq ($(COMPARE_BUILD), ) $(call CleanupCompareBuild) endif diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index d2291c50f2161c41ebd5681cecebc4c9b2a11471..ceb44f5519449c2ec0554a9c0ad1c6630eab5557 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,9 @@ 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") + export SOURCE_DATE_ISO_8601 := $$(call EpochToISO8601, $$(SOURCE_DATE_EPOCH)) endif endef @@ -469,10 +461,10 @@ else # $(HAS_SPEC)=true $(PRINTF) "\n=== Make failed targets repeated here ===\n" ; \ $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \ $(PRINTF) "=== End of repeated output ===\n" ; \ - $(PRINTF) "\nHint: Try searching the build log for the name of the first failed target.\n" ; \ + $(PRINTF) "\nHELP: Try searching the build log for the name of the first failed target.\n" ; \ else \ $(PRINTF) "\nNo indication of failed target found.\n" ; \ - $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \ + $(PRINTF) "HELP: Try searching the build log for '] Error'.\n" ; \ fi \ ) endef diff --git a/make/Main.gmk b/make/Main.gmk index 26e470f9c40a2e8bbb620e0cf963fa73bd196f13..45bed0d0457571f8e23a206a1cfcfcfb66006e16 100644 --- a/make/Main.gmk +++ b/make/Main.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 @@ -260,6 +260,13 @@ $(eval $(call SetupTarget, hotspot-ide-project, \ ALL_TARGETS += $(HOTSPOT_VARIANT_TARGETS) $(HOTSPOT_VARIANT_GENSRC_TARGETS) \ $(HOTSPOT_VARIANT_LIBS_TARGETS) +################################################################################ +# Help and user support + +$(eval $(call SetupTarget, doctor, \ + MAKEFILE := Doctor, \ +)) + ################################################################################ # Generate libs and launcher targets for creating compile_commands.json fragments define DeclareCompileCommandsRecipe 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 1611e9fd5312ee8ceb46f1a35cdaf926700daf70..953f29bddd5458a694ef8a347ae49cf18f82e834 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -348,7 +348,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], UTIL_LOOKUP_PROGS(DTRACE, dtrace, $PATH:/usr/sbin) UTIL_LOOKUP_PROGS(PATCH, gpatch patch) # Check if it's GNU time - IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` + [ IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU [Tt]ime'` ] if test "x$IS_GNU_TIME" != x; then IS_GNU_TIME=yes else diff --git a/make/autoconf/build-aux/config.guess b/make/autoconf/build-aux/config.guess index d589529f35aad914aac30789012a5beb3b47a8bb..6ae31e8ae22b1fca36c47b9ff7a1d86db8f3cebb 100644 --- a/make/autoconf/build-aux/config.guess +++ b/make/autoconf/build-aux/config.guess @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2021, Azul Systems, Inc. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -111,6 +111,15 @@ if [ "x$OUT" = x ]; then fi fi +# Test and fix RISC-V. +if [ "x$OUT" = x ]; then + if [ `uname -s` = Linux ]; then + if [ `uname -m` = riscv64 ]; then + OUT=riscv64-unknown-linux-gnu + fi + fi +fi + # Test and fix cpu on macos-aarch64, uname -p reports arm, buildsys expects aarch64 echo $OUT | grep arm-apple-darwin > /dev/null 2> /dev/null if test $? != 0; then diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index d52ad2c43159d7e7f1e9c9893158cb33921fc619..5e58696e34d38a2742c1c75dbd39d9d9bb904189 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -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) 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 486e78d4fcf99e178100c80553f403aa37ab244e..3d6963c7d4d09553d115d335161a6aae76bb0894 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -296,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 70806149203fe4535af18827cae3000fee622a53..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,4 +751,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], AC_SUBST(SOURCE_DATE) AC_SUBST(ENABLE_REPRODUCIBLE_BUILD) + 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/jvm-features.m4 b/make/autoconf/jvm-features.m4 index 8dfc0d362b9d385649d16d291e0e18d683c8af0e..ee1d19ecce8769b8b125022b8f47521daabd98ea 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -291,7 +291,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_SHENANDOAHGC], AC_MSG_CHECKING([if platform is supported by Shenandoah]) if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86" || \ test "x$OPENJDK_TARGET_CPU" = "xaarch64" || \ - test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then + test "x$OPENJDK_TARGET_CPU" = "xppc64le" || \ + test "x$OPENJDK_TARGET_CPU" = "xriscv64"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) @@ -341,7 +342,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_ZGC], AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) AVAILABLE=false fi - elif test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then + elif test "x$OPENJDK_TARGET_CPU" = "xppc64le" || \ + test "x$OPENJDK_TARGET_CPU" = "xriscv64"; then if test "x$OPENJDK_TARGET_OS" = "xlinux"; then AC_MSG_RESULT([yes]) else diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index fbc8ee7b9c8638fd639e3c34076a25bbce04dc4c..b901d77c5c5dff09f6a42bbf74a40b3e10fc2b7b 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.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 @@ -149,6 +149,12 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], fi fi + # Because RISC-V only has word-sized atomics, it requries libatomic where + # other common architectures do not. So link libatomic by default. + if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xriscv64; then + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -latomic" + fi + # perfstat lib if test "x$OPENJDK_TARGET_OS" = xaix; then BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat" diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 index 205d64f566d93a9a9c9d0b9191372e3aabb05143..a48aabe06f3a79662a6f93eb88c8e0d8531b296b 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.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 @@ -561,6 +561,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU_DEFINE=PPC64 elif test "x$OPENJDK_$1_CPU" = xppc64le; then HOTSPOT_$1_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_$1_CPU" = xriscv64; then + HOTSPOT_$1_CPU_DEFINE=RISCV64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then @@ -571,8 +573,6 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU_DEFINE=S390 elif test "x$OPENJDK_$1_CPU" = xs390x; then HOTSPOT_$1_CPU_DEFINE=S390 - elif test "x$OPENJDK_$1_CPU" = xriscv64; then - HOTSPOT_$1_CPU_DEFINE=RISCV elif test "x$OPENJDK_$1_CPU" != x; then HOTSPOT_$1_CPU_DEFINE=$(echo $OPENJDK_$1_CPU | tr a-z A-Z) fi diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 01bcc32a24e2cb7c6a3cb8d5f5ceaec796f24686..5671d4a9f3e5aa1a485ca38f6232598e29e61363 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -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@ diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 2288dda7ed632f2b7a22174da401b96451c6101b..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" @@ -901,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/Utils.gmk b/make/common/Utils.gmk index aba9a7cb417bbfdfa6fa3a38c2969889778dbd9a..bc2cd3d857be2365a79db67249f969b867c9a539 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -216,6 +216,21 @@ Or = \ $(strip $(if $(filter-out true false, $1), $(error Non-boolean values: $1)) \ $(if $(strip $(filter-out false, $1)), true, false)) + +################################################################################ +# Convert an UNIX epoch based timestamp (as an integer) to an ISO 8601 date +# string. +# Param 1 - timestamp +ifeq ($(IS_GNU_DATE), yes) + EpochToISO8601 = \ + $(shell $(DATE) --utc --date="@$(strip $1)" \ + +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null) +else + EpochToISO8601 = \ + $(shell $(DATE) -u -j -f "%s" "$(strip $1)" \ + +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null) +endif + ################################################################################ # Parse a multiple-keyword variable, like FOO="KEYWORD1=val1;KEYWORD2=val2;..." # These will be converted into a series of variables like FOO_KEYWORD1=val1, 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 5e4c5791859524511c954f8b6bc122f3a1233f90..1d9e1d1e3d08a780bb26d9109c7ea6407a75299c 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", + windows_x64: "VS2022-17.1.0+1.0", + linux_aarch64: "gcc11.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", linux_s390x: "gcc8.2.0-Fedora27+1.0" @@ -1447,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/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/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh index 059fb7acb6fb9fdb5722b6b288bee40d8421169a..5744863958c2ef626f9f553b40082bd780868aa7 100644 --- a/make/devkit/createJMHBundle.sh +++ b/make/devkit/createJMHBundle.sh @@ -26,7 +26,7 @@ # Create a bundle in the build directory, containing what's needed to # build and run JMH microbenchmarks from the OpenJDK build. -JMH_VERSION=1.34 +JMH_VERSION=1.35 COMMONS_MATH3_VERSION=3.2 JOPT_SIMPLE_VERSION=4.6 diff --git a/make/devkit/createWindowsDevkit2019.sh b/make/devkit/createWindowsDevkit.sh similarity index 91% rename from make/devkit/createWindowsDevkit2019.sh rename to make/devkit/createWindowsDevkit.sh index a5c89f09faac8532efd29a018ce09363fe110f0d..f738c3a89fb10f499ff321cc86ae472c6f291778 100644 --- a/make/devkit/createWindowsDevkit2019.sh +++ b/make/devkit/createWindowsDevkit.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2019, 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 @@ -28,14 +28,19 @@ # suitable for building OpenJDK and OracleJDK. Needs to run in Cygwin or WSL. # erik.joelsson@oracle.com -VS_VERSION="2019" -VS_VERSION_NUM_NODOT="160" +usage_and_exit() { + echo "Usage: createWindowsDevkit.sh <2019 | 2022>" + exit 1 +} + +if [ ! $# = 1 ]; then + usage_and_exit +fi + +VS_VERSION="$1" + VS_DLL_VERSION="140" SDK_VERSION="10" -SDK_FULL_VERSION="10.0.17763.0" -MSVC_DIR="Microsoft.VC142.CRT" -MSVC_FULL_VERSION="14.12.27508" -REDIST_FULL_VERSION="14.20.27508" SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)" BUILD_DIR="${SCRIPT_DIR}/../../build/devkit" @@ -66,13 +71,33 @@ fi # Work around the insanely named ProgramFiles(x86) env variable PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")" +PROGRAMFILES="$($WINDOWS_PATH_TO_UNIX_PATH "$PROGRAMFILES")" + +case $VS_VERSION in + 2019) + MSVC_PROGRAMFILES_DIR="${PROGRAMFILES_X86}" + MSVC_CRT_DIR="Microsoft.VC142.CRT" + VS_VERSION_NUM_NODOT="160" + ;; + + 2022) + MSVC_PROGRAMFILES_DIR="${PROGRAMFILES}" + MSVC_CRT_DIR="Microsoft.VC143.CRT" + VS_VERSION_NUM_NODOT="170" + ;; + *) + echo "Unexpected VS version: $VS_VERSION" + usage_and_exit + ;; +esac + # Find Visual Studio installation dir VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'` if [ -d "$VSNNNCOMNTOOLS" ]; then VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")" else - VS_INSTALL_DIR="${PROGRAMFILES_X86}/Microsoft Visual Studio/2019" + VS_INSTALL_DIR="${MSVC_PROGRAMFILES_DIR}/Microsoft Visual Studio/$VS_VERSION" VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)" fi echo "VS_INSTALL_DIR: $VS_INSTALL_DIR" @@ -101,9 +126,9 @@ DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" echo "Creating devkit in $DEVKIT_ROOT" -MSVCR_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}.dll -VCRUNTIME_1_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}_1.dll -MSVCP_DLL=${MSVC_DIR}/msvcp${VS_DLL_VERSION}.dll +MSVCR_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}.dll +VCRUNTIME_1_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}_1.dll +MSVCP_DLL=${MSVC_CRT_DIR}/msvcp${VS_DLL_VERSION}.dll ################################################################################ # Copy Visual Studio files diff --git a/make/devkit/createWindowsDevkit2017.sh b/make/devkit/createWindowsDevkit2017.sh deleted file mode 100644 index 42c132512930563fea14eca8464957a182921967..0000000000000000000000000000000000000000 --- a/make/devkit/createWindowsDevkit2017.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2015, 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. 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. -# - -# This script copies parts of a Visual Studio installation into a devkit -# suitable for building OpenJDK and OracleJDK. Needs to run in Cygwin or WSL. -# erik.joelsson@oracle.com - -VS_VERSION="2017" -VS_VERSION_NUM_NODOT="150" -VS_DLL_VERSION="140" -SDK_VERSION="10" -MSVC_DIR="Microsoft.VC141.CRT" - -SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)" -BUILD_DIR="${SCRIPT_DIR}/../../build/devkit" - -################################################################################ -# Prepare settings - -UNAME_SYSTEM=`uname -s` -UNAME_RELEASE=`uname -r` - -# Detect cygwin or WSL -IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN` -IS_WSL=`echo $UNAME_RELEASE | grep Microsoft` -if test "x$IS_CYGWIN" != "x"; then - BUILD_ENV="cygwin" -elif test "x$IS_WSL" != "x"; then - BUILD_ENV="wsl" -else - echo "Unknown environment; only Cygwin and WSL are supported." - exit 1 -fi - -if test "x$BUILD_ENV" = "xcygwin"; then - WINDOWS_PATH_TO_UNIX_PATH="cygpath -u" -elif test "x$BUILD_ENV" = "xwsl"; then - WINDOWS_PATH_TO_UNIX_PATH="wslpath -u" -fi - -# Work around the insanely named ProgramFiles(x86) env variable -PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")" - -# Find Visual Studio installation dir -VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'` -if [ -d "$VSNNNCOMNTOOLS" ]; then - VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")" -else - VS_INSTALL_DIR="${PROGRAMFILES_X86}/Microsoft Visual Studio/2017" - VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)" -fi -echo "VS_INSTALL_DIR: $VS_INSTALL_DIR" - -# Extract semantic version -POTENTIAL_INI_FILES="Common7/IDE/wdexpress.isolation.ini Common7/IDE/devenv.isolation.ini" -for f in $POTENTIAL_INI_FILES; do - if [ -f "$VS_INSTALL_DIR/$f" ]; then - VS_VERSION_SP="$(grep ^SemanticVersion= "$VS_INSTALL_DIR/$f")" - # Remove SemnaticVersion= - VS_VERSION_SP="${VS_VERSION_SP#*=}" - # Remove suffix of too detailed numbering starting with + - VS_VERSION_SP="${VS_VERSION_SP%+*}" - break - fi -done -if [ -z "$VS_VERSION_SP" ]; then - echo "Failed to find SP version" - exit 1 -fi -echo "Found Version SP: $VS_VERSION_SP" - -# Setup output dirs -DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit" -DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" - -echo "Creating devkit in $DEVKIT_ROOT" - -MSVCR_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}.dll -MSVCP_DLL=${MSVC_DIR}/msvcp${VS_DLL_VERSION}.dll - -################################################################################ -# Copy Visual Studio files - -TOOLS_VERSION="$(ls "$VS_INSTALL_DIR/VC/Tools/MSVC" | sort -r -n | head -n1)" -echo "Found Tools version: $TOOLS_VERSION" -VC_SUBDIR="VC/Tools/MSVC/$TOOLS_VERSION" -REDIST_VERSION="$(ls "$VS_INSTALL_DIR/VC/Redist/MSVC" | sort -r -n | head -n1)" -echo "Found Redist version: $REDIST_VERSION" -REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION" -echo "Copying VC..." -rm -rf $DEVKIT_ROOT/VC -mkdir -p $DEVKIT_ROOT/VC/bin -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/ -mkdir -p $DEVKIT_ROOT/VC/lib -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/arm64" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x64" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x86" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/include" $DEVKIT_ROOT/VC/ -mkdir -p $DEVKIT_ROOT/VC/atlmfc/lib -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/arm64" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x64" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x86" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/include" $DEVKIT_ROOT/VC/atlmfc/ -mkdir -p $DEVKIT_ROOT/VC/Auxiliary -cp -r "$VS_INSTALL_DIR/VC/Auxiliary/Build" $DEVKIT_ROOT/VC/Auxiliary/ -mkdir -p $DEVKIT_ROOT/VC/redist -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/arm64" $DEVKIT_ROOT/VC/redist/ -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x64" $DEVKIT_ROOT/VC/redist/ -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x86" $DEVKIT_ROOT/VC/redist/ - -# The redist runtime libs are needed to run the compiler but may not be -# installed on the machine where the devkit will be used. -cp $DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x86 -cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x86 -cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x64 -cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x64 -cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/arm64 -cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/arm64 - -################################################################################ -# Copy SDK files - -SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION" -echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR" - -SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)" -echo "Found SDK version: $SDK_FULL_VERSION" -UCRT_VERSION="$(ls "$SDK_INSTALL_DIR/Redist" | grep $SDK_VERSION | sort -r -n | head -n1)" -echo "Found UCRT version: $UCRT_VERSION" -echo "Copying SDK..." -rm -rf $DEVKIT_ROOT/$SDK_VERSION -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/bin -cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x64" $DEVKIT_ROOT/$SDK_VERSION/bin/ -cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x86" $DEVKIT_ROOT/$SDK_VERSION/bin/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/lib -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/Redist -cp -r "$SDK_INSTALL_DIR/Redist/$UCRT_VERSION/ucrt" $DEVKIT_ROOT/$SDK_VERSION/Redist/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/include -cp -r "$SDK_INSTALL_DIR/include/$SDK_FULL_VERSION/"* $DEVKIT_ROOT/$SDK_VERSION/include/ - -################################################################################ -# Generate devkit.info - -echo-info() { - echo "$1" >> $DEVKIT_ROOT/devkit.info -} - -echo "Generating devkit.info..." -rm -f $DEVKIT_ROOT/devkit.info -echo-info "# This file describes to configure how to interpret the contents of this devkit" -echo-info "DEVKIT_NAME=\"Microsoft Visual Studio $VS_VERSION $VS_VERSION_SP (devkit)\"" -echo-info "DEVKIT_VS_VERSION=\"$VS_VERSION\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_x86=\"\$DEVKIT_ROOT/VC/bin/x86:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_x86=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_x86=\"\$DEVKIT_ROOT/VC/lib/x86;\$DEVKIT_ROOT/VC/atlmfc/lib/x86;\$DEVKIT_ROOT/$SDK_VERSION/lib/x86\"" -echo-info "DEVKIT_MSVCR_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_x86=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x86\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_x86_64=\"\$DEVKIT_ROOT/VC/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_x86_64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_x86_64=\"\$DEVKIT_ROOT/VC/lib/x64;\$DEVKIT_ROOT/VC/atlmfc/lib/x64;\$DEVKIT_ROOT/$SDK_VERSION/lib/x64\"" -echo-info "DEVKIT_MSVCR_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_x86_64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x64\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_aarch64=\"\$DEVKIT_ROOT/VC/bin/arm64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_aarch64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_aarch64=\"\$DEVKIT_ROOT/VC/lib/arm64;\$DEVKIT_ROOT/VC/atlmfc/lib/arm64;\$DEVKIT_ROOT/$SDK_VERSION/lib/arm64\"" -echo-info "DEVKIT_MSVCR_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_aarch64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/arm64\"" -echo-info "" -echo-info "DEVKIT_TOOLS_VERSION=\"$TOOLS_VERSION\"" -echo-info "DEVKIT_REDIST_VERSION=\"$REDIST_VERSION\"" -echo-info "DEVKIT_SDK_VERSION=\"$SDK_FULL_VERSION\"" -echo-info "DEVKIT_UCRT_VERSION=\"$UCRT_VERSION\"" - -################################################################################ -# Copy this script - -echo "Copying this script..." -cp $0 $DEVKIT_ROOT/ - -################################################################################ -# Create bundle - -echo "Creating bundle: $DEVKIT_BUNDLE" -(cd "$DEVKIT_ROOT" && tar zcf "$DEVKIT_BUNDLE" .) diff --git a/make/hotspot/gensrc/GensrcAdlc.gmk b/make/hotspot/gensrc/GensrcAdlc.gmk index 25c132729142e426262022a700f1e925edd09972..73496bc6586c7229a876d06b61f503748311ef68 100644 --- a/make/hotspot/gensrc/GensrcAdlc.gmk +++ b/make/hotspot/gensrc/GensrcAdlc.gmk @@ -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 @@ -146,6 +146,13 @@ ifeq ($(call check-jvm-feature, compiler2), true) ))) endif + ifeq ($(HOTSPOT_TARGET_CPU_ARCH), riscv) + AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_v.ad \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_b.ad \ + ))) + endif + ifeq ($(call check-jvm-feature, shenandoahgc), true) AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU).ad \ 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/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..c410e390fc96e6a7a23641d05493870f7b48fe9a 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -470,7 +470,6 @@ else endif - LIBFONTMANAGER_EXTRA_HEADER_DIRS := \ libharfbuzz \ common/awt \ @@ -485,6 +484,14 @@ BUILD_LIBFONTMANAGER_FONTLIB += $(LIBFREETYPE_LIBS) LIBFONTMANAGER_OPTIMIZATION := HIGHEST +ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), ) + # gcc (and to an extent clang) is particularly bad at optimizing these files, + # causing a massive spike in compile time. We don't care about these + # particular files anyway, so lower optimization level. + BUILD_LIBFONTMANAGER_hb-subset.cc_OPTIMIZATION := SIZE + BUILD_LIBFONTMANAGER_hb-subset-plan.cc_OPTIMIZATION := SIZE +endif + ifeq ($(call isTargetOs, windows), true) LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \ X11TextRenderer.c @@ -742,7 +749,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/demo/share/jfc/CodePointIM/com/sun/inputmethods/internal/codepointim/CodePointInputMethodDescriptor.java b/src/demo/share/jfc/CodePointIM/com/sun/inputmethods/internal/codepointim/CodePointInputMethodDescriptor.java index 0e91e1916da77f3abf6b85ac216b3202751aef56..320a1ce7e669a772662894c99ee8eb41d66cffe4 100644 --- a/src/demo/share/jfc/CodePointIM/com/sun/inputmethods/internal/codepointim/CodePointInputMethodDescriptor.java +++ b/src/demo/share/jfc/CodePointIM/com/sun/inputmethods/internal/codepointim/CodePointInputMethodDescriptor.java @@ -75,7 +75,7 @@ public class CodePointInputMethodDescriptor implements InputMethodDescriptor { */ public Locale[] getAvailableLocales() { Locale[] locales = { - new Locale("", "", ""), }; + Locale.ROOT, }; return locales; } diff --git a/src/demo/share/jfc/CodePointIM/resources/codepoint_de.properties b/src/demo/share/jfc/CodePointIM/resources/codepoint_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..84597bb758cbc5e81226b8d063916ce4b6a8d089 --- /dev/null +++ b/src/demo/share/jfc/CodePointIM/resources/codepoint_de.properties @@ -0,0 +1,36 @@ +# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Resource strings for CodePointIM +# + +warning=Diese Demoeingabemethode kann nicht direkt als Anwendung ausgef\u00FChrt werden.\nIn der Datei README.html in diesem Verzeichnis erfahren Sie, wie Sie diese \nEingabemethode verwenden. + diff --git a/src/demo/share/jfc/Notepad/resources/Notepad_de.properties b/src/demo/share/jfc/Notepad/resources/Notepad_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..0c15bc05033da34a68fdcafdfd68ffa44b9c9196 --- /dev/null +++ b/src/demo/share/jfc/Notepad/resources/Notepad_de.properties @@ -0,0 +1,93 @@ +# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Resource strings for Notepad example + +Title=Notepad +ElementTreeFrameTitle=Elemente + +# file Menu definition +# +# Each of the strings that follow form a key to be +# used as the basis of a menu item definition. +# +# open -> Notepad.openAction +# new -> Notepad.newAction +# save -> Notepad.saveAction +# exit -> Notepad.exitAction + +fileLabel=Datei +openLabel=\u00D6ffnen +openImage=resources/open.gif +newLabel=Neu +newImage=resources/new.gif +saveLabel=Speichern +saveImage=resources/save.gif +exitLabel=Beenden + +# +# edit Menu definition +# +# cut -> JTextComponent.cutAction +# copy -> JTextComponent.copyAction +# paste -> JTextComponent.pasteAction + +editLabel=Bearbeiten +cutLabel=Ausschneiden +cutImage=resources/cut.gif +copyLabel=Kopieren +copyImage=resources/copy.gif +pasteLabel=Einf\u00FCgen +pasteImage=resources/paste.gif +undoLabel=R\u00FCckg\u00E4ngig +redoLabel=Wiederherstellen + +# +# debug Menu definition +# + +debugLabel=Debuggen +dumpLabel=Modell in System.err ausgeben +showElementTreeLabel=Elemente anzeigen + +# toolbar definition +# +# Each of the strings that follow form a key to be +# used as the basis of the tool definition. Actions +# are of course sharable, and in this case are shared +# with the menu items. + +newTooltip=Neue Datei erstellen +openTooltip=Datei \u00F6ffnen +saveTooltip=In Datei speichern +cutTooltip=Auswahl in Zwischenablage verschieben +copyTooltip=Auswahl in Zwischenablage kopieren +pasteTooltip=Zwischenablage in Auswahl einf\u00FCgen diff --git a/src/demo/share/jfc/Stylepad/resources/Stylepad_de.properties b/src/demo/share/jfc/Stylepad/resources/Stylepad_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..7ab06001f6d8e583805e43a6a7550c34e88346a9 --- /dev/null +++ b/src/demo/share/jfc/Stylepad/resources/Stylepad_de.properties @@ -0,0 +1,88 @@ +# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Resource strings for Stylepad example + +Title=Stylepad + +# Menu labels +colorLabel=Farbe +Red=Rot +Green=Gr\u00FCn +Blue=Blau + +boldLabel=Fett +italicLabel=Kursiv + +# font menu + +fontLabel=Schriftart +family1Label=SansSerif +family2Label=Monospaced +family3Label=Serif +family4Label=Lucida Sans +size1Label=10 +size2Label=12 +size3Label=18 +size4Label=24 +size5Label=48 +boldLabel=Fett +italicLabel=Kursiv +underlineLabel=Unterstrichen + +# +# debug Menu definition +# +debugLabel=Debuggen +dumpLabel=Modell in System.err ausgeben +showElementTreeLabel=Elemente anzeigen + + +# toolbar definition +boldImage=resources/bold.gif +boldTooltip=Fett +italicImage=resources/italic.gif +italicTooltip=Kursiv +underlineImage=resources/underline.gif +underlineTooltip=Unterstrichen +foregroundImage=resources/fg.gif +leftImage=resources/left.gif +leftTooltip=Linksb\u00FCndig +centerImage=resources/center.gif +centerTooltip=Zentriert +rightImage=resources/right.gif +rightTooltip=Rechtsb\u00FCndig +bulletsImage=resources/bullets.gif + +# wonderland example images +aliceGif=resources/alice.gif +caterpillarGif=resources/caterpillar.gif +hatterGif=resources/hatter.gif diff --git a/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties b/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..509597076f77650de23fcc19b51d39bd1c34f63f --- /dev/null +++ b/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties @@ -0,0 +1,674 @@ +# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# This properties file is used to create a PropertyResourceBundle +# It contains Locale specific strings used in the SwingSet demo. +# +# @author Jeff Dinkins + +################################# +### SwingSet Infrastructure ### +################################# + +### About Box ### + +AboutBox.title=Info zu Swing! +AboutBox.ok_button_text=OK +AboutBox.accessible_description=SwingSet2-Demo: Copyright (c) 2011, Oracle und/oder verbundene Unternehmen. All rights reserved. Alle Rechte vorbehalten. + +### Source Code ### +SourceCode.loading=Quellcode wird geladen und formatiert. Bitte warten... + +### Status ### + +Status.loading=Wird geladen: +Status.popupMenuAccessible=Dr\u00FCcken Sie Umschalt-F10, um das Popup-Men\u00FC zu aktivieren + +### Menu Bar ### + +MenuBar.accessible_description=Men\u00FCleiste der Swing-Demo + + +### Frame ### + +Frame.title=SwingSet2 + + +### Tabbed Pane ### + +TabbedPane.src.labelAndMnemonic=Quellcode +TabbedPane.src_tooltip=Quellcode f\u00FCr diese Demo anzeigen + + +### Look & Feel Menu ### + +LafMenu.laf.labelAndMnemonic=&Look-and-Feel +LafMenu.laf_accessible_description=Men\u00FC, \u00FCber das Sie das Look-and-Feel wechseln k\u00F6nnen + +LafMenu.java.labelAndMnemonic=&Java-Look-and-Feel +LafMenu.java_accessible_description=Das Java-Look-and-Feel + +LafMenu.nimbus.labelAndMnemonic=&Nimbus-Look-and-Feel +LafMenu.nimbus_accessible_description=Das Nimbus-Look-and-Feel + +LafMenu.mac.labelAndMnemonic=&Mac OS X-Look-and-Feel +LafMenu.mac_accessible_description=Das Mac OS X-Look-and-Feel + +LafMenu.motif.labelAndMnemonic=M&otif-Look-and-Feel +LafMenu.motif_accessible_description=Das Motif-Look-and-Feel + +LafMenu.windows.labelAndMnemonic=&Windows-Look-and-Feel +LafMenu.windows_accessible_description=Windows-Look-and-Feel + +LafMenu.gtk.labelAndMnemonic=>K-Look-and-Feel +LafMenu.gtk_accessible_description=GTK-Look-and-Feel + + +### Themes Menu ### + +ThemesMenu.themes.labelAndMnemonic=&Themes +ThemesMenu.themes_accessible_description=Men\u00FC zum Wechseln der Metal-Farb-Themes + +ThemesMenu.aqua.labelAndMnemonic=A&qua +ThemesMenu.aqua_accessible_description=Ein Metal-Theme mit blau-gr\u00FCnen Farben + +ThemesMenu.charcoal.labelAndMnemonic=&Anthrazit +ThemesMenu.charcoal_accessible_description=Ein Metal-Theme mit dunkelgrauen Farben + +ThemesMenu.contrast.labelAndMnemonic=&Hoher Kontrast +ThemesMenu.contrast_accessible_description=Ein Theme mit hohem Kontrast + +ThemesMenu.ocean.labelAndMnemonic=&Ozean +ThemesMenu.ocean_accessible_description=Das Metal-Theme "Ozean" + +ThemesMenu.steel.labelAndMnemonic=&Stahl +ThemesMenu.steel_accessible_description=Das blaue/violette Metal-Theme + +ThemesMenu.emerald.labelAndMnemonic=&Smaragdgr\u00FCn +ThemesMenu.emerald_accessible_description=Ein Metal-Theme mit gr\u00FCnen Farben + +ThemesMenu.ruby.labelAndMnemonic=&Rubinrot +ThemesMenu.ruby_accessible_description=Ein Metal-Theme mit roten Farben + + +### Font SubMenu (under Themes) +FontMenu.fonts.labelAndMnemonic=Schri&ftarten +FontMenu.fonts_accessible_description=Men\u00FC, in dem Sie Schriftarten f\u00FCr das Java-Look-and-Feel ausw\u00E4hlen + +FontMenu.bold.labelAndMnemonic=&Fett +FontMenu.bold_accessible_description=Deaktiviert fettgedruckte Schriftarten f\u00FCr das Java-Look-and-Feel + +FontMenu.plain.labelAndMnemonic=&Normal +FontMenu.plain_accessible_description=Deaktiviert normale Schriftarten f\u00FCr das Java-Look-and-Feel + + +### Audio SubMenu (under Themes) ### + +AudioMenu.audio.labelAndMnemonic=&Audio +AudioMenu.audio_accessible_description=Men\u00FC, in dem Sie die verf\u00FCgbare Audio-Feedbackmenge im Java-Look-and-Feel \u00E4ndern + +AudioMenu.on.labelAndMnemonic=&Ein +AudioMenu.on_accessible_description=Aktiviert das gesamte Audiofeedback f\u00FCr das Java-Look-and-Feel + +AudioMenu.default.labelAndMnemonic=Stan&dard +AudioMenu.default_accessible_description=Aktiviert die standardm\u00E4\u00DFige Audio-Feedbackmenge f\u00FCr das Java-Look-and-Feel + +AudioMenu.off.labelAndMnemonic=A&us +AudioMenu.off_accessible_description=Deaktiviert das gesamte Audiofeedback f\u00FCr das Java-Look-and-Feel + +### Options Menu ### + +OptionsMenu.options.labelAndMnemonic=O&ptionen +OptionsMenu.options_accessible_description=Men\u00FC mit anderen Optionen + +OptionsMenu.tooltip.labelAndMnemonic=QuickInfo ak&tivieren +OptionsMenu.tooltip_accessible_description=QuickInfo aktivieren oder deaktivieren + +OptionsMenu.dragEnabled.labelAndMnemonic=&Drag-und-Drop aktivieren +OptionsMenu.dragEnabled_accessible_description=Drag-und-Drop aktivieren oder deaktivieren + +### File Menu ### + +FileMenu.file.labelAndMnemonic=Dat&ei +FileMenu.accessible_description=Men\u00FC "Datei" +FileMenu.about.labelAndMnemonic=&Info +FileMenu.about_accessible_description=Weitere Informationen zur SwingSet2-Anwendung +FileMenu.open.labelAndMnemonic=\u00D6&ffnen +FileMenu.open_accessible_description=Platzhaltermen\u00FCoption zum \u00D6ffnen einer Datei +FileMenu.save.labelAndMnemonic=&Speichern +FileMenu.save_accessible_description=Platzhaltermen\u00FCoption zum Speichern einer Datei +FileMenu.save_as.labelAndMnemonic=Speichern &unter... +FileMenu.save_as_accessible_description=Platzhaltermen\u00FCoption zum Speichern einer Datei mit einem neuen Namen +FileMenu.exit.labelAndMnemonic=B&eenden +FileMenu.exit_accessible_description=SwingSet2-Anwendung beenden + +### Multi-Screen menu ### +MultiMenu.multi.labelAndMnemonic=&Multiscreen +MultiMenu.multi_accessible_description=Multiscreen-Men\u00FC +MultiMenu.all.labelAndMnemonic=SwingSet2 &auf allen Bildschirmen erstellen +MultiMenu.all_accessible_description=SwingSet2-Fenster auf jedem Bildschirm erstellen +MultiMenu.single.labelAndMnemonic=SwingSet2 auf Bildschirm erstellen +MultiMenu.single_accessible_description=SwingSet2-Fenster auf Bildschirm erstellen + + +################################ +### DEMOS ### +################################ + +### Button Demo ### + +ButtonDemo.accessible_description=Die ButtonDemo zeigt Beispiele f\u00FCr die Verwendung von JButton, JRadioButton, JToggleButton und JCheckBox +ButtonDemo.tooltip=Demos f\u00FCr JButton, JRadioButton, JToggleButton, JCheckbox +ButtonDemo.name=Schaltfl\u00E4chendemo + +ButtonDemo.buttons=Schaltfl\u00E4chen +ButtonDemo.checkboxes=Kontrollk\u00E4stchen +ButtonDemo.radiobuttons=Optionsfelder +ButtonDemo.togglebuttons=Umschalt-Schaltfl\u00E4chen + +ButtonDemo.textbuttons=Textschaltfl\u00E4chen +ButtonDemo.imagebuttons=Bildschaltfl\u00E4chen +ButtonDemo.textradiobuttons=Textoptionsfelder +ButtonDemo.imageradiobuttons=Bildoptionsfelder +ButtonDemo.texttogglebuttons=Text-Umschalt-Schaltfl\u00E4chen +ButtonDemo.imagetogglebuttons=Bild-Umschalt-Schaltfl\u00E4chen +ButtonDemo.textcheckboxes=Textkontrollk\u00E4stchen +ButtonDemo.imagecheckboxes=Bildkontrollk\u00E4stchen + +ButtonDemo.button1=Eins +ButtonDemo.button2=Zwei +ButtonDemo.button3=Drei. + +ButtonDemo.radio1=Optionsfeld Eins +ButtonDemo.radio2=Optionsfeld Zwei +ButtonDemo.radio3=Optionsfeld Drei +ButtonDemo.radioX=Drei(HTML!) + +ButtonDemo.check1=Eins +ButtonDemo.check2=Zwei +ButtonDemo.check3=Drei +ButtonDemo.checkX=Drei(HTML!) + +ButtonDemo.customradio=Ein benutzerdefiniertes "Chrome"-Optionsfeld. +ButtonDemo.customcheck=Ein benutzerdefinierbares Gl\u00FChbirnenkontrollk\u00E4stchen. + +ButtonDemo.phone=Telefon +ButtonDemo.write=Schreiben +ButtonDemo.peace=Peace + +ButtonDemo.controlpanel.labelAndMnemonic=Anzeigeoptionen: +ButtonDemo.paintborder.labelAndMnemonic=Rahmen f\u00E4r&ben +ButtonDemo.paintborder_tooltip=Klicken Sie hier, um die Rahmenf\u00E4rbung ein- oder auszuschalten. +ButtonDemo.paintfocus.labelAndMnemonic=&Fokus f\u00E4rben +ButtonDemo.paintfocus_tooltip=Klicken Sie hier, um die Fokusf\u00E4rbung ein- oder auszuschalten. +ButtonDemo.enabled.labelAndMnemonic=Aktivi&ert +ButtonDemo.enabled_tooltip=Klicken Sie hier, um die Schaltfl\u00E4chen zu aktivieren oder zu deaktivieren. +ButtonDemo.contentfilled.labelAndMnemonic=&Inhalt gef\u00FCllt +ButtonDemo.contentfilled_tooltip=Klicken Sie hier, um die F\u00FCllung des Inhaltsbereichs zu steuern. + +ButtonDemo.padamount.labelAndMnemonic=Abstand: +ButtonDemo.default.labelAndMnemonic=Stan&dard +ButtonDemo.default_tooltip=Verwendet den Standardabstand zwischen Rahmen und Label. +ButtonDemo.zero.labelAndMnemonic=&0 +ButtonDemo.zero_tooltip=Verwendet keinen Abstand zwischen Rahmen und Label. +ButtonDemo.ten.labelAndMnemonic=&10 +ButtonDemo.ten_tooltip=Verwendet einen Abstand von 10 Pixel zwischen Rahmen und Label. + +LayoutControlPanel.textposition.labelAndMnemonic=Textposition: +LayoutControlPanel.contentalignment.labelAndMnemonic=Inhaltsausrichtung: + +### ColorChooser Demo ### + +ColorChooserDemo.accessible_description=Mit dem ColorChooser k\u00F6nnen Sie eine Farbe \u00FCber eine Palette oder unter RGB- oder HSB-Werten ausw\u00E4hlen +ColorChooserDemo.tooltip=JColorChooser-Demo +ColorChooserDemo.name=ColorChooser-Demo +ColorChooserDemo.chooser_title=Farbe w\u00E4hlen +ColorChooserDemo.background=Hintergrund +ColorChooserDemo.grad_a=Farbverlauf 1 +ColorChooserDemo.grad_b=Farbverlauf 2 +ColorChooserDemo.outer_line=Umfang +ColorChooserDemo.cup=Bild der Kaffeetasse der Java-Marke + +### ComboBox Demo ### + +ComboBoxDemo.accessible_description=Diese Demo zeigt ein Beispiel f\u00FCr die Verwendung der JComboBox-Komponente. +ComboBoxDemo.tooltip=JComboBox-Demo +ComboBoxDemo.name=ComboBox-Demo + +ComboBoxDemo.hair=Haare +ComboBoxDemo.eyes=Augen +ComboBoxDemo.mouth=Mund +ComboBoxDemo.presets=Voreinstellungen: + +ComboBoxDemo.preset1=Philip, Howard, Jeff +ComboBoxDemo.preset2=Jeff, Larry, Philip +ComboBoxDemo.preset3=Howard, Scott, Hans +ComboBoxDemo.preset4=Philip, Jeff, Hans +ComboBoxDemo.preset5=Brent, Jon, Scott +ComboBoxDemo.preset6=Lara, Larry, Lisa +ComboBoxDemo.preset7=James, Philip, Michael +ComboBoxDemo.preset8=Philip, Lisa, Brent +ComboBoxDemo.preset9=James, Philip, Jon +ComboBoxDemo.preset10=Lara, Jon, Scott + + +ComboBoxDemo.hair_description=Haare: +ComboBoxDemo.eyes_description=Augen und Nase: +ComboBoxDemo.mouth_description=Mund: + +ComboBoxDemo.amy=Amy +ComboBoxDemo.brent=Brent +ComboBoxDemo.georges=Georges +ComboBoxDemo.hans=Hans +ComboBoxDemo.howard=Howard +ComboBoxDemo.james=James +ComboBoxDemo.jeff=Jeff +ComboBoxDemo.jon=Jon +ComboBoxDemo.lara=Lara +ComboBoxDemo.larry=Larry +ComboBoxDemo.lisa=Lisa +ComboBoxDemo.michael=Michael +ComboBoxDemo.philip=Philip +ComboBoxDemo.scott=Scott + +### FileChooser Demo ### + +FileChooserDemo.accessible_description=\u00DCber den FileChooser k\u00F6nnen Benutzer eine Datei zum \u00D6ffnen oder Erstellen/Speichern ausw\u00E4hlen. +FileChooserDemo.tooltip=JFileChooser-Demo +FileChooserDemo.name=FileChooser-Demo + +FileChooserDemo.plainbutton=Einfachen JFileChooser anzeigen +FileChooserDemo.previewbutton=Vorschau-JFileChooser anzeigen +FileChooserDemo.custombutton=Benutzerdefinierten JFileChooser anzeigen + +FileChooserDemo.description=&  &  Beachten Sie, dass Sie ganz einfach Ihren eigenen FileChooser
      &  &  mit beliebig vielen Komponenten erstellen k\u00F6nnen. + +FileChooserDemo.filterdescription=JPEG- und GIF-Bilddateien + +FileChooserDemo.nofileselected=W\u00E4hlen Sie zun\u00E4chst eine Datei aus. +FileChooserDemo.thefile=die Datei: +FileChooserDemo.isprobably=ist wahrscheinlich ein Bild. + +FileChooserDemo.helptext=Suchen: Datei suchen.
      Info: Weitere Informationen zur Datei.
      OK: Diese Datei ausw\u00E4hlen.
      Abbrechen: Dieses Dialogfeld ohne Aktion verlassen. + +FileChooserDemo.findquestion=Datei suchen: +FileChooserDemo.findresponse=
      Sie m\u00F6chten wirklich eine Datei suchen?
      Das ist mit dieser Demo nicht m\u00F6glich.
      + +FileChooserDemo.dialogtitle=FileChooser mit benutzerdefiniertem Layout +FileChooserDemo.help=Hilfe +FileChooserDemo.find=Suchen +FileChooserDemo.ok=OK +FileChooserDemo.about=Info +FileChooserDemo.cancel=Abbrechen + +### Html Demo ### + +HtmlDemo.accessible_description=Diese Demo zeigt, wie HTML-Text mit der JEditorPane-Komponente angezeigt wird. +HtmlDemo.tooltip=JEditorPane-HTML-Demo +HtmlDemo.name=JEditorPane-HTML-Demo +HtmlDemo.filename=swing.html + + +### Internal Frame Demo ### + +InternalFrameDemo.accessible_description=JInternal-Framedemo +InternalFrameDemo.create_frames.labelAndMnemonic=Angepasste interne Frames erstellen +InternalFrameDemo.title_text_field.labelAndMnemonic=Frametitel: +InternalFrameDemo.frame.labelAndMnemonic=Frame +InternalFrameDemo.palette.labelAndMnemonic=Generator f\u00FCr interne Frames +InternalFrameDemo.name=Demo f\u00FCr interne Frames +InternalFrameDemo.tooltip=JInternalFrame-Demo +InternalFrameDemo.closable.labelAndMnemonic=Kann geschlossen werden +InternalFrameDemo.resizable.labelAndMnemonic=Skalierbar +InternalFrameDemo.iconifiable.labelAndMnemonic=Als Symbol darstellbar +InternalFrameDemo.maximizable.labelAndMnemonic=Maximierbar +InternalFrameDemo.toast=Prost +InternalFrameDemo.duke=Euer Gnaden! +InternalFrameDemo.duchess=Herzogin +InternalFrameDemo.cab=Braucht jemand ein Taxi? + + +### List Demo ### + +ListDemo.accessible_description=JList-Demo +ListDemo.name=Listendemo +ListDemo.tooltip=JList-Demo +ListDemo.prefixes=Pr\u00E4fixe +ListDemo.suffixes=Suffixe +ListDemo.count.labelAndMnemonic=Anzahl generierte Listeneintr\u00E4ge: +ListDemo.all=Alle +ListDemo.none=Kein Wert +ListDemo.red=Rotes Firmenlogobild +ListDemo.yellow=Rotes Firmenlogobild +ListDemo.blue=Blaues Firmenlogobild +ListDemo.gray=Graues Firmenlogobild +ListDemo.green=Gr\u00FCnes Firmenlogobild +ListDemo.magenta=Firmenlogobild in Magenta +ListDemo.cyan=Firmenlogobild in Zyan +ListDemo.description=

      Diese Demo zeigt die Pr\u00E4sentation von Datenlisten auf zwei verschiedene Arten. Links steht eine JList-Komponente mit Listenelementen, die aus den Permutationen der aktivierten Pr\u00E4fixe und Suffixe bestehen. Die Kontrollk\u00E4stchenspalten f\u00FCr Pr\u00E4fix und Suffix rechts werden mit einer JPanel-Komponente mit einem Y-Achsen-BoxLayout in einer JScrollPane-Komponente erstellt.

      + + +### OptionPane Demo ### + +OptionPaneDemo.accessible_description=Die OptionPane-Demo zeigt Beispiele f\u00FCr die Verwendung von JOptionPane zum Generieren verschiedener g\u00E4ngiger Optionsdialogfelder +OptionPaneDemo.tooltip=JOptionPane-Demo +OptionPaneDemo.name=Optionsbereichsdemo + +OptionPaneDemo.warningbutton=Warnungsdialogfeld anzeigen +OptionPaneDemo.componentbutton=Komponentendialogfeld anzeigen +OptionPaneDemo.inputbutton=Eingabedialogfeld anzeigen +OptionPaneDemo.confirmbutton=Best\u00E4tigungsdialogfeld anzeigen +OptionPaneDemo.messagebutton=Meldungsdialog anzeigen + +OptionPaneDemo.warningtitle=Beispiel f\u00FCr Warnungsdialogfeld +OptionPaneDemo.warningtext=

      Das ist ein Test des Notfallwarnsystems. Das ist
      nur ein Test
      . Der Webmaster Ihres lokalen Intranets hat dieses System in freiwilliger
      Zusammenarbeit mit den Bundes- und L\u00E4nderbeh\u00F6rden
      entwickelt, um Sie bei Bedarf \u00FCber
      Notf\u00E4lle zu informieren. Bei einem tats\u00E4chlichen Notfall w\u00FCrden auf das Signal, das Sie
      eben geh\u00F6rt haben, offizielle Informationen, Nachrichten
      oder Anweisungen folgen. Damit ist dieser Test des
      Notfallwarnsystems
      abgeschlossen.


      Entwicklerhinweis: Der Text in dieser Dialogfelddemo wurde mit HTML formatiert.

      + +OptionPaneDemo.messagetext=Flaschenpost + +OptionPaneDemo.confirmquestion=Scheint heute die Sonne? +OptionPaneDemo.confirmyes=Warum sitzen Sie noch am Computer?
      Gehen Sie raus! Machen Sie einen Ausflug zum Strand! Legen Sie sich in die Sonne! +OptionPaneDemo.confirmno=Gut, dass Sie hier drinnen vor dem Wetter gesch\u00FCtzt sind. + +OptionPaneDemo.inputquestion=Was ist Ihr Lieblingsfilm? +OptionPaneDemo.inputresponse=Das ist ein guter Film! + +OptionPaneDemo.componenttitle=Beispiel f\u00FCr Komponentendialogfeld +OptionPaneDemo.componentmessage=JOptionPane kann beliebig viele Komponenten
      enthalten, wie ein Textfeld: +OptionPaneDemo.componenttextfield=oder ein Kombinationsfeld: +OptionPaneDemo.component_cb1=Element 1 +OptionPaneDemo.component_cb2=Element 2 +OptionPaneDemo.component_cb3=Element 3 +OptionPaneDemo.componentmessage2=JOptionPane kann au\u00DFerdem beliebig viele
      Optionen anzeigen: +OptionPaneDemo.component_op1=Ja +OptionPaneDemo.component_op2=Nein +OptionPaneDemo.component_op3=Vielleicht +OptionPaneDemo.component_op4=Wahrscheinlich +OptionPaneDemo.component_op5=Abbrechen + +OptionPaneDemo.component_r1=Optimistisch und positiv! Das ist gut. +OptionPaneDemo.component_r2=Definitiv nicht. Da haben Sie ganz recht. +OptionPaneDemo.component_r3= Ja, momentan ist die Situation
      noch ungekl\u00E4rt. Sagen Sie sp\u00E4ter Bescheid, wenn Sie es genau wissen.
      +OptionPaneDemo.component_r4=Sie wollen doch "Ja" sagen. Sie h\u00E4tten sich
      einfach darauf einlassen und "Ja" klicken sollen.
      + +### ProgressBar Demo ### + +ProgressBarDemo.accessible_description=Diese Demo zeigt ein Beispiel f\u00FCr die Verwendung der JProgressBar-Komponente. +ProgressBarDemo.tooltip=JProgressBar-Demo +ProgressBarDemo.name=ProgressBar-Demo +ProgressBarDemo.start_button=Laden von Text starten +ProgressBarDemo.stop_button=Laden von Text stoppen +ProgressBarDemo.accessible_text_loading_progress=Ladefortschritt f\u00FCr Text +ProgressBarDemo.accessible_text_area_name=Text wird progressiv geladen + +ProgressBarDemo.accessible_text_area_description=Diese JTextArea-Komponente wird progressiv mit Text aus einem Puffer gef\u00FCllt (ein Buchstabe nach dem anderen). Dabei wird der Ladefortschritt im Fortschrittsbalken unten im Fenster angezeigt + +ProgressBarDemo.text=Man sagt ja, dass unendlich viele Affen, die unendlich lange auf unendlich vielen Schreibmaschinen herumtippen, \nirgendwann alle Meisterwerke der Menschheit schreiben w\u00FCrden. Mit den modernen Hochgeschwindigkeitsrechnern k\u00F6nnen wir \ndiese Theorie endlich testen... \n\n\tLzskd jfy 92y;ho4 th;qlh sd 6yty;q2 hnlj 8sdf. Djfy 92y;ho4, th;qxhz d7yty; \n\tQ0hnlj 23&&^ (# ljask djf y92y; fy92y; Sd6y ty;q2h nl jk la gfa harvin garvel\n\tlasdfsd a83sl la8z ks8l 92y;ho4 th;qlh sd 6yty;q2 hnlj 8sdf. Djfy 92y;ho4,\n\tth;qxhz d7yty; Q0hnlj 23&&^ nknod mrs88 jsd79lfm#%$JLaoz6df lso7dj f2 jfls\n\t67d9ol1@2fou99s 1lkj2 @l.k1 2; a89o7aljf 1l3i7ou8 d8l3 lqwerty0092 #1!\n\tja9o do8lkjj139rojsd9**!l6*hd # ljasd78 l2awkjad78 3ol7asljf 3 ldif && l.js\n\tLl ls ewan la8uj 23lll7u 8l 3h hhxx8 8d lsd fixx 891lkjno99sl d8l@@@!!8#8\n\tdfoil jarooda mklaoorj nowai the smisthliylka jkdlfjiw ladajadra lthhheeejfjl\n\tdkddooolda bub mirznod of the koojgaf!! But 2 be or not to be... that is the\n\tquestion. Then when shall we three meet again In thunder, lightning, or in\n\train? When the hurlyburly's done, When the battle's lost and won. That will\n\tbe ere the set of sun. Where the place? Upon the heath. There to meet with\n\tMacbeth. But hath forth not to want..... a banana, or to be.... a banana.\n\tBanana, I knew him banana. Banana banana. Banana banana banana banana.\n\n\n\n\nNun, das war scheinbar eine gute Idee... + + +### ScrollPane Demo ### + +ScrollPaneDemo.accessible_description=JScrollPane-Demo +ScrollPaneDemo.name=Demo f\u00FCr Bildlaufbereich +ScrollPaneDemo.tooltip=JScrollPane-Demo +ScrollPaneDemo.crayons=Viele Stifte +ScrollPaneDemo.colheader=Spaltenheader +ScrollPaneDemo.rowheader=Zeilenheader +ScrollPaneDemo.upperleft=Oben links +ScrollPaneDemo.upperright=Oben rechts im Spaltenheader +ScrollPaneDemo.lowerleft=Unten links im Spaltenheader + + +### Slider Demo ### + +SliderDemo.accessible_description=Diese Demo zeigt ein Beispiel f\u00FCr die Verwendung der JSlider-Komponente. +SliderDemo.tooltip=JSlider-Demo +SliderDemo.name=Schiebereglerdemo + +SliderDemo.slidervalue=Schiebereglerwert: +SliderDemo.horizontal=Horizontal +SliderDemo.vertical=Vertikal +SliderDemo.plain=Einfach +SliderDemo.a_plain_slider=Ein einfacher Schieberegler +SliderDemo.majorticks=Grobteilungen +SliderDemo.majorticksdescription=Ein Schieberegler mit Grobteilungsmarkierungen +SliderDemo.ticks=Feinteilungen, Teilungen zum Einrasten und Labels +SliderDemo.minorticks=Feinteilungen +SliderDemo.minorticksdescription=Ein Schieberegler mit Grob- und Feinteilungen, mit Teilungen, in die der Schieberegler einrastet, wobei einige Teilungen mit einem sichtbaren Label versehen sind +SliderDemo.disabled=Deaktiviert +SliderDemo.disableddescription=Ein Schieberegler mit Grob- und Feinteilungen, der nicht aktiviert ist (kann nicht bearbeitet werden) + +### SplitPane Demo ### + +SplitPaneDemo.accessible_description=JSplitPane-Demo +SplitPaneDemo.name=Teilbereichdemo +SplitPaneDemo.tooltip=JSplitPane-Demo +SplitPaneDemo.earth=Mutter Erde +SplitPaneDemo.moon=Ein Astronaut auf dem Mond +SplitPaneDemo.vert_split.labelAndMnemonic=&Vertikal geteilt +SplitPaneDemo.horz_split.labelAndMnemonic=Ho&rizontal geteilt +SplitPaneDemo.cont_layout.labelAndMnemonic=Kontinuierli&ches Layout +SplitPaneDemo.one_touch_expandable.labelAndMnemonic=&Mit einer Ber\u00FChrung einblendbar +SplitPaneDemo.divider_size.labelAndMnemonic=Trennliniengr\u00F6\u00DFe +SplitPaneDemo.invalid_divider_size=Ung\u00FCltige Trennliniengr\u00F6\u00DFe +SplitPaneDemo.error=Fehler +SplitPaneDemo.first_component_min_size.labelAndMnemonic=M&indestgr\u00F6\u00DFe der ersten Komponente +SplitPaneDemo.second_component_min_size.labelAndMnemonic=Mi&ndestgr\u00F6\u00DFe der zweiten Komponente +SplitPaneDemo.invalid_min_size=Ung\u00FCltige Mindestgr\u00F6\u00DFe +SplitPaneDemo.must_be_greater_than=muss gr\u00F6\u00DFer sein als + + +### TabbedPane Demo ### + +TabbedPaneDemo.accessible_description=Diese Demo zeigt ein Beispiel f\u00FCr die Verwendung der JTabbedPane-Komponente. +TabbedPaneDemo.tooltip=JTabbedPane-Demo +TabbedPaneDemo.name=TabbedPane-Demo + +TabbedPaneDemo.bounce=
      Bouncing Babies!
      +TabbedPaneDemo.stephen=Stephen +TabbedPaneDemo.david=David +TabbedPaneDemo.matthew=Matthew +TabbedPaneDemo.ewan=Ewan +TabbedPaneDemo.blake=Blake +TabbedPaneDemo.brooke=Brooke +TabbedPaneDemo.laine=Laine +TabbedPaneDemo.hania=Hania + +TabbedPaneDemo.label=Platzierung der Registerkarten: +TabbedPaneDemo.top=Oben +TabbedPaneDemo.bottom=Unten +TabbedPaneDemo.left=Links +TabbedPaneDemo.right=Rechts + + +### Table Demo ### + +TableDemo.accessible_description=JTable-Demo +TableDemo.name=Tabellendemo +TableDemo.tooltip=JTable-Demo +TableDemo.all_columns=Alle Spalten +TableDemo.autoresize_mode=Modus "Automatische Skalierung" +TableDemo.cell_selection=Zellenauswahl +TableDemo.column_boundaries=Spaltengrenzen +TableDemo.column_selection=Spaltenauswahl +TableDemo.horz_lines=Horizontale Linien +TableDemo.intercell_spacing=Abstand zwischen Zellen +TableDemo.intercell_spacing_colon=Abstand zwischen Zellen: +TableDemo.last_column=Letzte Spalte +TableDemo.multiple_ranges=Mehrere Bereiche +TableDemo.one_range=Ein Bereich +TableDemo.reordering_allowed=Neuanordnung zul\u00E4ssig +TableDemo.row_height=Zeilenh\u00F6he +TableDemo.row_height_colon=Zeilenh\u00F6he: +TableDemo.row_selection=Zeilenauswahl +TableDemo.selection_mode=Auswahlmodus +TableDemo.subsequent_columns=Nachfolgende Spalten +TableDemo.vert_lines=Vertikale Linien +TableDemo.single=Einzeln +TableDemo.none=Kein Wert +TableDemo.off=Deaktiviert +TableDemo.first_name=Vorname +TableDemo.last_name=Nachname +TableDemo.favorite_color=Lieblingsfarbe +TableDemo.favorite_food=Lieblingsessen +TableDemo.favorite_movie=Lieblingsfilm +TableDemo.favorite_number=Lieblingszahl +TableDemo.aqua=Aquamarin +TableDemo.beige=Beige +TableDemo.black=Schwarz +TableDemo.blue=Blau +TableDemo.cybergreen=Gr\u00FCn +TableDemo.darkgreen=Dunkelgr\u00FCn +TableDemo.eblue=Neonblau +TableDemo.jfcblue=JFC prim\u00E4r +TableDemo.jfcblue2=JFC sekund\u00E4r +TableDemo.forestgreen=Waldgr\u00FCn +TableDemo.gray=Grau +TableDemo.green=Gr\u00FCn +TableDemo.orange=Orange +TableDemo.purple=Lila +TableDemo.red=Rot +TableDemo.rustred=Rostrot +TableDemo.sunpurple=Purpur +TableDemo.suspectpink=Pink +TableDemo.turquoise=T\u00FCrkis +TableDemo.violet=Violett +TableDemo.yellow=Gelb +TableDemo.2001=2001: Odyssee im Weltraum +TableDemo.buckaroo=Buckaroo Banzai - Die 8. Dimension +TableDemo.firstsight=Auf den ersten Blick +TableDemo.airplane=Die unglaubliche Reise in einem verr\u00FCckten Flugzeug (und Fortsetzung) +TableDemo.aliens=Aliens - Die R\u00FCckkehr +TableDemo.bicycle=Fahrraddiebe +TableDemo.bladerunner=Blade Runner (Director's Cut) +TableDemo.bluesbros=Blues Brothers +TableDemo.brazil=Brazil +TableDemo.bugs=Das gro\u00DFe Krabbeln +TableDemo.city=Die Stadt der verlorenen Kinder +TableDemo.chusingura=Chusingura (1962) +TableDemo.clock=Uhrwerk Orange +TableDemo.curse=Der Fluch des D\u00E4monen +TableDemo.dasboot=Das Boot +TableDemo.dazed=Confusion - Sommer der Ausgeflippten +TableDemo.defending=Rendezvous im Jenseits +TableDemo.eraserhead=Eraserhead +TableDemo.fifthelement=Das f\u00FCnfte Element +TableDemo.goodfellas=GoodFellas - Drei Jahrzehnte in der Mafia +TableDemo.harold=Harold und Maude +TableDemo.joyluck=T\u00F6chter des Himmels +TableDemo.jules=Jules und Jim +TableDemo.ladyvanishes=Eine Dame verschwindet +TableDemo.mohicans=Der letzte Mohikaner +TableDemo.lonestar=Lone Star +TableDemo.man=Der Mann, der zuviel wusste +TableDemo.musicman=Music Man +TableDemo.dog=Mein Leben als Hund +TableDemo.oncewest=Spiel mir das Lied vom Tod +TableDemo.pulpfiction=Pulp Fiction +TableDemo.raiders=J\u00E4ger des verlorenen Schatzes +TableDemo.reservoir=Reservoir Dogs - Wilde Hunde +TableDemo.repoman=Repoman +TableDemo.spinaltap=This is Spinal Tap +TableDemo.schindlerslist=Schindlers Liste +TableDemo.starwars=Star Wars +TableDemo.stuntman=Der lange Tod des Stuntman Cameron +TableDemo.thinman=Der d\u00FCnne Mann +TableDemo.withnail=Withnail && I +TableDemo.labyrinth=Die Reise ins Labyrinth +TableDemo.shawshank=Die Verurteilten +TableDemo.apple=Apfel +TableDemo.asparagus=Spargel +TableDemo.banana=Banane +TableDemo.broccoli=Brokkoli +TableDemo.carrot=Karotte +TableDemo.cantaloupe=Cantaloupe-Melone +TableDemo.corn=Mais +TableDemo.grapes=Trauben +TableDemo.grapefruit=Grapefruit +TableDemo.kiwi=Kiwi +TableDemo.onion=Zwiebel +TableDemo.pear=Birne +TableDemo.peach=Pfirsich +TableDemo.pepper=Rote Paprika +TableDemo.pickle=Essiggurke +TableDemo.pineapple=Ananas +TableDemo.raspberry=Himbeere +TableDemo.sparegrass=Gr\u00FCnzeug +TableDemo.strawberry=Erdbeere +TableDemo.tomato=Tomate +TableDemo.watermelon=Wassermelone + +TableDemo.printing=Drucken +TableDemo.fitWidth=Breite anpassen +TableDemo.print=Drucken +TableDemo.header=Header + +# This string will be formatted by a MessageFormat and +# printed at the top of each page of the printed result. +# You can use {0} to insert a page number. +TableDemo.headerText=JTable-Druck + +TableDemo.footer=Footer + +# This string will be formatted by a MessageFormat and +# printed at the bottom of each page of the printed result. +# You can use {0} to insert a page number. +TableDemo.footerText=Seite {0} + +TableDemo.printingResult=Druckergebnis +TableDemo.printingComplete=Druck abgeschlossen +TableDemo.printingCancelled=Druck abgebrochen + +# This string will be formatted by a MessageFormat and +# and displayed when an exception occurs. +# {0} is used to place details of the exception. +TableDemo.printingFailed=Druck nicht erfolgreich: {0} + + +### ToolTip Demo ### + +ToolTipDemo.accessible_description=QuickInfos zeigen kurze Hilfebeschreibungen f\u00FCr eine Komponente an +ToolTipDemo.accessible_cow=Das ist eine Kuh. +ToolTipDemo.tooltip=QuickInfo-Demo +ToolTipDemo.name=QuickInfo-Demo +ToolTipDemo.bessie=Bessie, die Kuh +ToolTipDemo.cow=Kuh. +ToolTipDemo.got_milk=Milch gef\u00E4llig? +ToolTipDemo.tail=Schweif. +ToolTipDemo.moo=Muuuh +ToolTipDemo.tooltip_features=QuickInfos m\u00FCssen nicht immer

      langweilige, einzeilige Beschreibungen sein. Das Swing!-Team

      zeigt Ihnen gerne, dass es auch anders geht.

      In Swing k\u00F6nnen QuickInfos HTML f\u00FCr Folgendes verwenden:

      • Listen
      • fettgedruckten Text
      • betonten Text
      • Text mit Farben
      • Text in unterschiedlichen Gr\u00F6\u00DFen
      • und Schriftarten
      Au\u00DFerdem k\u00F6nnen sie auch mehrere Zeilen umfassen. + + +### Tree Demo ### + +TreeDemo.accessible_description=Diese Demo zeigt ein Beispiel f\u00FCr die Verwendung einer JTree-Komponente. +TreeDemo.tooltip=JTree-Demo +TreeDemo.name=Baumdemo +TreeDemo.music=Musik + diff --git a/src/demo/share/jfc/SwingSet2/resources/swingset_ja.properties b/src/demo/share/jfc/SwingSet2/resources/swingset_ja.properties index bc6a24781e961eef8806fe58aba22ecd14a8bf88..ebb0409561b006e659a81f67cf0b41f6eeed8fa9 100644 --- a/src/demo/share/jfc/SwingSet2/resources/swingset_ja.properties +++ b/src/demo/share/jfc/SwingSet2/resources/swingset_ja.properties @@ -1,4 +1,4 @@ -# Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -316,7 +316,7 @@ FileChooserDemo.nofileselected=\u6700\u521D\u306B\u30D5\u30A1\u30A4\u30EB\u3092\ FileChooserDemo.thefile=\u30D5\u30A1\u30A4\u30EB\u540D: FileChooserDemo.isprobably=\u306F\u304A\u305D\u3089\u304F\u753B\u50CF\u30C7\u30FC\u30BF\u3067\u3059\u3002 -FileChooserDemo.helptext=\u691C\u7D22: \u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u307E\u3059\u3002
      \u8A73\u7D30: \u30D5\u30A1\u30A4\u30EB\u306B\u3064\u3044\u3066\u306E\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\u3002
      OK: \u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3057\u307E\u3059\u3002
      \u53D6\u6D88: \u4F55\u3082\u305B\u305A\u306B\u3053\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u9589\u3058\u307E\u3059\u3002 +FileChooserDemo.helptext=\u691C\u7D22: \u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u307E\u3059\u3002
      \u8A73\u7D30: \u30D5\u30A1\u30A4\u30EB\u306B\u3064\u3044\u3066\u3055\u3089\u306B\u5B66\u7FD2\u3057\u307E\u3059\u3002
      OK: \u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3057\u307E\u3059\u3002
      \u53D6\u6D88: \u4F55\u3082\u305B\u305A\u306B\u3053\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u9589\u3058\u307E\u3059\u3002 FileChooserDemo.findquestion=\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u7D22: FileChooserDemo.findresponse=
      \u3042\u306A\u305F\u3001\u672C\u5F53\u306B\u79C1\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u3066\u307B\u3057\u3044\u3068\u601D\u3063\u3066\u308B\u3093\u3067\u3059\u304B\u3002
      \u305D\u3093\u306A\u3053\u3068\u3067\u304D\u306A\u3044\u3067\u3059\u3088\u3001\u3084\u308A\u65B9\u77E5\u3089\u306A\u3044\u3093\u3067\u3059\u304B\u3089\u3002\u79C1\u306F\u305F\u3060\u306E\u30C7\u30E2\u30FB\u30D7\u30ED\u30B0\u30E9\u30E0\u3067\u3059\u3088\u3002
      diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f21835f9de3ef99ec1209b753749fada25aa6b8d..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 @@ -17071,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..0be4d5414ee7ba20353d2a581fc0397b1c47efbb 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 @@ -350,16 +350,23 @@ instruct vcvt4Bto4I(vecX dst, vecD src) ins_pipe(pipe_class_default); %} -instruct vcvt2Lto2F(vecD dst, vecX src) +instruct vcvt2Lto2F(vecD dst, vecX src, vRegF tmp) %{ predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); match(Set dst (VectorCastL2X src)); - format %{ "scvtfv T2D, $dst, $src\n\t" - "fcvtn $dst, T2S, $dst, T2D\t# convert 2L to 2F vector" + effect(TEMP_DEF dst, TEMP tmp); + format %{ "umov rscratch1, $src, D, 0\n\t" + "scvtfs $dst, rscratch1\n\t" + "umov rscratch1, $src, D, 1\n\t" + "scvtfs $tmp, rscratch1\n\t" + "ins $dst, S, $tmp, 1, 0\t# convert 2L to 2F vector" %} ins_encode %{ - __ scvtfv(__ T2D, as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg)); - __ fcvtn(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($dst$$reg), __ T2D); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 0); + __ scvtfs(as_FloatRegister($dst$$reg), rscratch1); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 1); + __ scvtfs(as_FloatRegister($tmp$$reg), rscratch1); + __ ins(as_FloatRegister($dst$$reg), __ S, as_FloatRegister($tmp$$reg), 1, 0); %} ins_pipe(pipe_slow); %} @@ -4266,6 +4273,47 @@ instruct vsqrt2D(vecX dst, vecX src) // --------------------------------- NEG -------------------------------------- +instruct vnegID(vecD dst, vecD src) +%{ + predicate(n->as_Vector()->length_in_bytes() < 16); + match(Set dst (NegVI src)); + ins_cost(INSN_COST); + format %{ "negr $dst, $src\t# vector (8B/4H/2S)" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_Arrangement size = __ esize2arrangement((unsigned)type2aelembytes(bt), false); + __ negr(as_FloatRegister($dst$$reg), size, as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp64); +%} + +instruct vnegIX(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (NegVI src)); + ins_cost(INSN_COST); + format %{ "negr $dst, $src\t# vector (16B/8H/4S)" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_Arrangement size = __ esize2arrangement((unsigned)type2aelembytes(bt), true); + __ negr(as_FloatRegister($dst$$reg), size, as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp128); +%} + +instruct vneg2L(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (NegVL src)); + ins_cost(INSN_COST); + format %{ "negr $dst,$src\t# vector (2D)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp128); +%} + instruct vneg2F(vecD dst, vecD src) %{ predicate(n->as_Vector()->length() == 2); @@ -4400,11 +4448,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 +4466,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 +4477,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 +4539,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 +4548,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 %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ 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($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 %{ + __ 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($tmp$$reg), __ T8B, + __ 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 +4702,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 +4721,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 +4763,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 +4782,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 +4814,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 %{ + __ 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($tmp$$reg), __ T16B, + __ 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 %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ 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($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 +4959,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 +4978,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 +5020,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 +5039,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 +5071,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 %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ 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($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 +5205,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 +5218,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 +5231,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 +5244,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 +5257,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 +5282,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 %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ 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($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 +5356,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 +5369,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 +5385,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 +5399,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 +5413,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 +5427,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 +5441,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 +5454,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 +5467,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 +5480,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 +5495,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 +5510,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 +5525,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 +5540,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 +5553,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 +5566,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..2f3520329080708e0335d21e1fe0c9434853549c 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 @@ -178,16 +178,23 @@ VECTOR_CAST_I2I_L(4, I, B, D, X, xtn, 4S, 4H, 8H, 8B) VECTOR_CAST_I2I_L(4, B, I, X, D, sxtl, 8B, 8H, 4H, 4S) dnl -instruct vcvt2Lto2F(vecD dst, vecX src) +instruct vcvt2Lto2F(vecD dst, vecX src, vRegF tmp) %{ predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); match(Set dst (VectorCastL2X src)); - format %{ "scvtfv T2D, $dst, $src\n\t" - "fcvtn $dst, T2S, $dst, T2D\t# convert 2L to 2F vector" + effect(TEMP_DEF dst, TEMP tmp); + format %{ "umov rscratch1, $src, D, 0\n\t" + "scvtfs $dst, rscratch1\n\t" + "umov rscratch1, $src, D, 1\n\t" + "scvtfs $tmp, rscratch1\n\t" + "ins $dst, S, $tmp, 1, 0\t# convert 2L to 2F vector" %} ins_encode %{ - __ scvtfv(__ T2D, as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg)); - __ fcvtn(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($dst$$reg), __ T2D); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 0); + __ scvtfs(as_FloatRegister($dst$$reg), rscratch1); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 1); + __ scvtfs(as_FloatRegister($tmp$$reg), rscratch1); + __ ins(as_FloatRegister($dst$$reg), __ S, as_FloatRegister($tmp$$reg), 1, 0); %} ins_pipe(pipe_slow); %} @@ -1923,20 +1930,39 @@ VSQRT(fsqrt, 4, F, X, S) VSQRT(fsqrt, 2, D, X, D) // --------------------------------- NEG -------------------------------------- +define(`VNEGI', ` +instruct vnegI$1(vec$1 dst, vec$1 src) +%{ + predicate(n->as_Vector()->length_in_bytes() ifelse($1, D, <, ==) 16); + match(Set dst (NegVI src)); + ins_cost(INSN_COST); + format %{ "negr $dst, $src\t# vector ($2)" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_Arrangement size = __ esize2arrangement((unsigned)type2aelembytes(bt), ifelse($1, D, false, true)); + __ negr(as_FloatRegister($dst$$reg), size, as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp`'ifelse($1, D, 64, 128)); +%}')dnl +dnl $1 $2 +VNEGI(D, 8B/4H/2S) +VNEGI(X, 16B/8H/4S) +dnl define(`VNEG', ` instruct vneg$2$3`'(vec$4 dst, vec$4 src) %{ predicate(n->as_Vector()->length() == $2); match(Set dst (NegV$3 src)); - ins_cost(INSN_COST * 3); + ins_cost(INSN_COST`'ifelse($3, L, `',` * 3')); format %{ "$1 $dst,$src\t# vector ($2$5)" %} ins_encode %{ - __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + __ $1(as_FloatRegister($dst$$reg), __ T$2$5, as_FloatRegister($src$$reg)); %} ins_pipe(vunop_fp`'ifelse($4, D, 64, 128)); %}')dnl dnl $1 $2 $3 $4 $5 +VNEG(negr, 2, L, X, D) VNEG(fneg, 2, F, D, S) VNEG(fneg, 4, F, X, S) VNEG(fneg, 2, D, X, D) @@ -1972,223 +1998,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 %{ + __ sshl(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(`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 %{ - __ $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, + __ 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 %{ - __ $1(as_FloatRegister($tmp$$reg), __ T`'ifelse($6, D, 8B, 16B), + __ ushl(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(`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 %{ + __ negr(as_FloatRegister($dst$$reg), __ T`'ifelse($4, D, 8B, 16B), + as_FloatRegister($shift$$reg)); + __ 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 +2279,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 +2288,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/aarch64_sve.ad b/src/hotspot/cpu/aarch64/aarch64_sve.ad index c048a463c1a4ffeded90e57911c23ffecaeab080..165a6444f8394a97e7d97d86dcc8c98c4aae79e6 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve.ad +++ b/src/hotspot/cpu/aarch64/aarch64_sve.ad @@ -305,12 +305,12 @@ instruct loadV_partial(vReg dst, vmemA mem, pRegGov pgtmp, rFlagsReg cr) %{ match(Set dst (LoadVector mem)); effect(TEMP pgtmp, KILL cr); ins_cost(6 * SVE_COST); - format %{ "sve_whilelo_zr_imm $pgtmp, vector_length\n\t" + format %{ "sve_ptrue $pgtmp, vector_length\n\t" "sve_ldr $dst, $pgtmp, $mem\t# load vector partial" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this)); FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, dst_reg, as_PRegister($pgtmp$$reg), bt, bt, $mem->opcode(), @@ -325,12 +325,12 @@ instruct storeV_partial(vReg src, vmemA mem, pRegGov pgtmp, rFlagsReg cr) %{ match(Set mem (StoreVector mem src)); effect(TEMP pgtmp, KILL cr); ins_cost(5 * SVE_COST); - format %{ "sve_whilelo_zr_imm $pgtmp, vector_length\n\t" + format %{ "sve_ptrue $pgtmp, vector_length\n\t" "sve_str $src, $pgtmp, $mem\t# store vector partial" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this, $src)); FloatRegister src_reg = as_FloatRegister($src$$reg); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, src_reg, as_PRegister($pgtmp$$reg), bt, bt, $mem->opcode(), @@ -365,8 +365,8 @@ instruct loadV_masked_partial(vReg dst, vmemA mem, pRegGov pg, pRegGov pgtmp, rF format %{ "sve_ldr $dst, $pg, $mem\t# load vector predicated partial (sve)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this)); __ sve_and(as_PRegister($pgtmp$$reg), as_PRegister($pgtmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, as_FloatRegister($dst$$reg), @@ -400,8 +400,8 @@ instruct storeV_masked_partial(vReg src, vmemA mem, pRegGov pg, pRegGov pgtmp, r format %{ "sve_str $mem, $pg, $src\t# store vector predicated partial (sve)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($pgtmp$$reg), as_PRegister($pgtmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, as_FloatRegister($src$$reg), @@ -438,7 +438,7 @@ instruct vmaskAllI(pRegGov dst, iRegIorL2I src, vReg tmp, rFlagsReg cr) %{ effect(TEMP tmp, KILL cr); ins_cost(3 * SVE_COST); format %{ "sve_dup $tmp, $src\n\t" - "sve_ptrue_lanecnt $dst\n\t" + "sve_ptrue $dst, vector_length\n\t" "sve_cmpne $dst, $dst, $tmp, 0\t# mask all (sve) (B/H/S)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); @@ -481,7 +481,7 @@ instruct vmaskAllL(pRegGov dst, iRegL src, vReg tmp, rFlagsReg cr) %{ effect(TEMP tmp, KILL cr); ins_cost(3 * SVE_COST); format %{ "sve_dup $tmp, $src\n\t" - "sve_ptrue_lanecnt $dst\n\t" + "sve_ptrue $dst, vector_length\n\t" "sve_cmpne $dst, $dst, $tmp, 0\t# mask all (sve) (D)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); @@ -591,7 +591,7 @@ instruct reinterpretResize(vReg dst, vReg src, pRegGov pgtmp, rFlagsReg cr) %{ length_in_bytes_src : length_in_bytes_dst; assert(length_in_bytes_src <= MaxVectorSize && length_in_bytes_dst <= MaxVectorSize, "invalid vector length"); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ B, length_in_bytes_resize); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ B, length_in_bytes_resize); __ sve_dup(as_FloatRegister($dst$$reg), __ B, 0); __ sve_sel(as_FloatRegister($dst$$reg), __ B, as_PRegister($pgtmp$$reg), as_FloatRegister($src$$reg), as_FloatRegister($dst$$reg)); @@ -1544,10 +1544,10 @@ instruct vfmlaD(vReg dst_src1, vReg src2, vReg src3) %{ ins_pipe(pipe_slow); %} -// vector fmla - predicated +// vector fmad - predicated // dst_src1 = dst_src1 * src2 + src3 -instruct vfmlaF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ +instruct vfmadF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ predicate(UseFMA && UseSVE > 0); match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary src3 pg))); ins_cost(SVE_COST); @@ -1560,7 +1560,7 @@ instruct vfmlaF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ %} // dst_src1 = dst_src1 * src2 + src3 -instruct vfmlaD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ +instruct vfmadD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ predicate(UseFMA && UseSVE > 0); match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary src3 pg))); ins_cost(SVE_COST); @@ -1575,10 +1575,25 @@ instruct vfmlaD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ // vector fmls // dst_src1 = dst_src1 + -src2 * src3 -// dst_src1 = dst_src1 + src2 * -src3 -instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegVF must not be predicated. +instruct vfmlsF1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ S, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * -src3 +// The NegVF must not be predicated. +instruct vfmlsF2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3)))); ins_cost(SVE_COST); format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (S)" %} @@ -1590,10 +1605,25 @@ instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{ %} // dst_src1 = dst_src1 + -src2 * src3 -// dst_src1 = dst_src1 + src2 * -src3 -instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegVD must not be predicated. +instruct vfmlsD1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ D, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * -src3 +// The NegVD must not be predicated. +instruct vfmlsD2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3)))); ins_cost(SVE_COST); format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (D)" %} @@ -1604,13 +1634,62 @@ instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{ ins_pipe(pipe_slow); %} +// vector fmsb - predicated + +// dst_src1 = dst_src1 * -src2 + src3 +// The NegVF must not be predicated. +instruct vfmsbF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary src3 pg))); + ins_cost(SVE_COST); + format %{ "sve_fmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_fmsb(as_FloatRegister($dst_src1$$reg), __ S, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 * -src2 + src3 +// The NegVD must not be predicated. +instruct vfmsbD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary src3 pg))); + ins_cost(SVE_COST); + format %{ "sve_fmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_fmsb(as_FloatRegister($dst_src1$$reg), __ D, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector fnmla // dst_src1 = -dst_src1 + -src2 * src3 -// dst_src1 = -dst_src1 + src2 * -src3 -instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegVF must not be predicated. +instruct vfnmlaF1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ S, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -dst_src1 + src2 * -src3 +// The NegVF must not be predicated. +instruct vfnmlaF2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3)))); ins_cost(SVE_COST); format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (S)" %} @@ -1622,10 +1701,27 @@ instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{ %} // dst_src1 = -dst_src1 + -src2 * src3 -// dst_src1 = -dst_src1 + src2 * -src3 -instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegVD must not be predicated. +instruct vfnmlaD1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ D, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -dst_src1 + src2 * -src3 +// The NegVD must not be predicated. +instruct vfnmlaD2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3)))); ins_cost(SVE_COST); format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (D)" %} @@ -1636,11 +1732,47 @@ instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{ ins_pipe(pipe_slow); %} +// vector fnmad - predicated + +// dst_src1 = -src3 + dst_src1 * -src2 +// The NegVF must not be predicated. +instruct vfnmadF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary (NegVF src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmad $dst_src1, $pg, $src2, $src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_fnmad(as_FloatRegister($dst_src1$$reg), __ S, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -src3 + dst_src1 * -src2 +// The NegVD must not be predicated. +instruct vfnmadD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary (NegVD src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmad $dst_src1, $pg, $src2, $src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_fnmad(as_FloatRegister($dst_src1$$reg), __ D, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector fnmls // dst_src1 = -dst_src1 + src2 * src3 +// The NegVF must not be predicated. instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3))); ins_cost(SVE_COST); format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) (S)" %} @@ -1652,8 +1784,10 @@ instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{ %} // dst_src1 = -dst_src1 + src2 * src3 +// The NegVD must not be predicated. instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3))); ins_cost(SVE_COST); format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) (D)" %} @@ -1664,6 +1798,38 @@ instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{ ins_pipe(pipe_slow); %} +// vector fnmsb - predicated + +// dst_src1 = -src3 + dst_src1 * src2 +// The NegVF must not be predicated. +instruct vfnmsbF_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary (NegVF src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_fnmsb(as_FloatRegister($dst_src1$$reg), __ S, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -src3 + dst_src1 * src2 +// The NegVD must not be predicated. +instruct vfnmsbD_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary (NegVD src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_fnmsb(as_FloatRegister($dst_src1$$reg), __ D, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector mla // dst_src1 = dst_src1 + src2 * src3 @@ -1722,6 +1888,64 @@ instruct vmlaL(vReg dst_src1, vReg src2, vReg src3) ins_pipe(pipe_slow); %} +// vector mla - predicated + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaB_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (AddVB (Binary dst_src1 (MulVB src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mla $dst_src1, $pg, src2, src3\t # vector (sve) (B)" %} + ins_encode %{ + __ sve_mla(as_FloatRegister($dst_src1$$reg), __ B, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaS_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (AddVS (Binary dst_src1 (MulVS src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mla $dst_src1, $pg, src2, src3\t # vector (sve) (H)" %} + ins_encode %{ + __ sve_mla(as_FloatRegister($dst_src1$$reg), __ H, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaI_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (AddVI (Binary dst_src1 (MulVI src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mla $dst_src1, $pg, src2, src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_mla(as_FloatRegister($dst_src1$$reg), __ S, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaL_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (AddVL (Binary dst_src1 (MulVL src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mla $dst_src1, $pg, src2, src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_mla(as_FloatRegister($dst_src1$$reg), __ D, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector mls // dst_src1 = dst_src1 - src2 * src3 @@ -1780,6 +2004,64 @@ instruct vmlsL(vReg dst_src1, vReg src2, vReg src3) ins_pipe(pipe_slow); %} +// vector mls - predicated + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsB_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (SubVB (Binary dst_src1 (MulVB src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mls $dst_src1, $pg, src2, src3\t # vector (sve) (B)" %} + ins_encode %{ + __ sve_mls(as_FloatRegister($dst_src1$$reg), __ B, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsS_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (SubVS (Binary dst_src1 (MulVS src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mls $dst_src1, $pg, src2, src3\t # vector (sve) (H)" %} + ins_encode %{ + __ sve_mls(as_FloatRegister($dst_src1$$reg), __ H, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsI_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (SubVI (Binary dst_src1 (MulVI src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mls $dst_src1, $pg, src2, src3\t # vector (sve) (S)" %} + ins_encode %{ + __ sve_mls(as_FloatRegister($dst_src1$$reg), __ S, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsL_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (SubVL (Binary dst_src1 (MulVL src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mls $dst_src1, $pg, src2, src3\t # vector (sve) (D)" %} + ins_encode %{ + __ sve_mls(as_FloatRegister($dst_src1$$reg), __ D, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector mul instruct vmulB(vReg dst_src1, vReg src2) %{ @@ -1936,7 +2218,34 @@ instruct vmulD_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ ins_pipe(pipe_slow); %} -// vector fneg +// vector neg + +instruct vnegI(vReg dst, vReg src) %{ + predicate(UseSVE > 0 && + !n->as_Vector()->is_predicated_vector()); + match(Set dst (NegVI src)); + ins_cost(SVE_COST); + format %{ "sve_neg $dst, $src\t# vector (sve) (B/H/S)" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_neg(as_FloatRegister($dst$$reg), __ elemType_to_regVariant(bt), + ptrue, as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vnegL(vReg dst, vReg src) %{ + predicate(UseSVE > 0 && + !n->as_Vector()->is_predicated_vector()); + match(Set dst (NegVL src)); + ins_cost(SVE_COST); + format %{ "sve_neg $dst, $src\t# vector (sve) (D)" %} + ins_encode %{ + __ sve_neg(as_FloatRegister($dst$$reg), __ D, + ptrue, as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} instruct vnegF(vReg dst, vReg src) %{ predicate(UseSVE > 0 && @@ -1964,7 +2273,34 @@ instruct vnegD(vReg dst, vReg src) %{ ins_pipe(pipe_slow); %} -// vector fneg - predicated +// vector neg - predicated + +instruct vnegI_masked(vReg dst_src, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst_src (NegVI dst_src pg)); + ins_cost(SVE_COST); + format %{ "sve_neg $dst_src, $pg, $dst_src\t# vector (sve) (B/H/S)" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_neg(as_FloatRegister($dst_src$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), + as_FloatRegister($dst_src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vnegL_masked(vReg dst_src, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst_src (NegVL dst_src pg)); + ins_cost(SVE_COST); + format %{ "sve_neg $dst_src, $pg, $dst_src\t# vector (sve) (D)" %} + ins_encode %{ + __ sve_neg(as_FloatRegister($dst_src$$reg), __ D, + as_PRegister($pg$$reg), + as_FloatRegister($dst_src$$reg)); + %} + ins_pipe(pipe_slow); +%} instruct vnegF_masked(vReg dst_src, pRegGov pg) %{ predicate(UseSVE > 0); @@ -2147,7 +2483,7 @@ instruct vloadmask_loadV_partial(pRegGov dst, indirect mem, vReg vtmp, pRegGov p // expected vector element type. Convert the vector to predicate. BasicType to_vect_bt = Matcher::vector_element_basic_type(this); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(to_vect_bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, as_FloatRegister($vtmp$$reg), as_PRegister($ptmp$$reg), T_BOOLEAN, to_vect_bt, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -2194,7 +2530,7 @@ instruct storeV_vstoremask_partial(indirect mem, pRegGov src, vReg vtmp, BasicType from_vect_bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(from_vect_bt); __ sve_cpy(as_FloatRegister($vtmp$$reg), size, as_PRegister($src$$reg), 1, false); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, as_FloatRegister($vtmp$$reg), as_PRegister($ptmp$$reg), T_BOOLEAN, from_vect_bt, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -2272,8 +2608,7 @@ instruct reduce_addI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vt ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2290,8 +2625,7 @@ instruct reduce_addL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_addL $dst, $src1, $src2\t# addL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2307,8 +2641,7 @@ instruct reduce_addF_partial(vRegF src1_dst, vReg src2, pRegGov ptmp, rFlagsReg effect(TEMP ptmp, KILL cr); format %{ "sve_reduce_addF $src1_dst, $src1_dst, $src2\t# addF reduction partial (sve) (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ S, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); %} @@ -2323,8 +2656,7 @@ instruct reduce_addD_partial(vRegD src1_dst, vReg src2, pRegGov ptmp, rFlagsReg effect(TEMP ptmp, KILL cr); format %{ "sve_reduce_addD $src1_dst, $src1_dst, $src2\t# addD reduction partial (sve) (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ D, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); %} @@ -2401,8 +2733,7 @@ instruct reduce_addI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, v ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -2421,8 +2752,7 @@ instruct reduce_addL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD ins_cost(3 * SVE_COST); format %{ "sve_reduce_addL $dst, $src1, $pg, $src2\t# addL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -2440,8 +2770,7 @@ instruct reduce_addF_masked_partial(vRegF src1_dst, vReg src2, pRegGov pg, pRegG ins_cost(SVE_COST); format %{ "sve_reduce_addF $src1_dst, $pg, $src2\t# addF reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ S, @@ -2458,8 +2787,7 @@ instruct reduce_addD_masked_partial(vRegD src1_dst, vReg src2, pRegGov pg, pRegG ins_cost(SVE_COST); format %{ "sve_reduce_addD $src1_dst, $pg, $src2\t# addD reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ D, @@ -2515,8 +2843,7 @@ instruct reduce_andI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vt ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2534,8 +2861,7 @@ instruct reduce_andL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_andL $dst, $src1, $src2\t# andL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2590,8 +2916,7 @@ instruct reduce_andI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, v ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -2611,8 +2936,7 @@ instruct reduce_andL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD ins_cost(3 * SVE_COST); format %{ "sve_reduce_andL $dst, $src1, $pg, $src2\t# andL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -2669,8 +2993,7 @@ instruct reduce_orI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vtm ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2688,8 +3011,7 @@ instruct reduce_orL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_orL $dst, $src1, $src2\t# orL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2744,8 +3066,7 @@ instruct reduce_orI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vR ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -2765,8 +3086,7 @@ instruct reduce_orL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD v ins_cost(3 * SVE_COST); format %{ "sve_reduce_orL $dst, $src1, $pg, $src2\t# orL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -2823,8 +3143,7 @@ instruct reduce_eorI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vt ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2842,8 +3161,7 @@ instruct reduce_eorL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_eorL $dst, $src1, $src2\t# eorL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2898,8 +3216,7 @@ instruct reduce_eorI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, v ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -2919,8 +3236,7 @@ instruct reduce_eorL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD ins_cost(3 * SVE_COST); format %{ "sve_reduce_eorL $dst, $src1, $pg, $src2\t# eorL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -2979,8 +3295,7 @@ instruct reduce_maxI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vt ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -2998,8 +3313,7 @@ instruct reduce_maxL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_maxL $dst, $src1, $src2\t# maxL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -3032,8 +3346,7 @@ instruct reduce_maxF_partial(vRegF dst, vRegF src1, vReg src2, effect(TEMP_DEF dst, TEMP ptmp, KILL cr); format %{ "sve_reduce_maxF $dst, $src1, $src2\t# maxF reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_fmaxv(as_FloatRegister($dst$$reg), __ S, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); __ fmaxs(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg)); %} @@ -3065,8 +3378,7 @@ instruct reduce_maxD_partial(vRegD dst, vRegD src1, vReg src2, effect(TEMP_DEF dst, TEMP ptmp, KILL cr); format %{ "sve_reduce_maxD $dst, $src1, $src2\t# maxD reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_fmaxv(as_FloatRegister($dst$$reg), __ D, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); __ fmaxd(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg)); %} @@ -3124,8 +3436,7 @@ instruct reduce_maxI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, v ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -3145,8 +3456,7 @@ instruct reduce_maxL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD ins_cost(3 * SVE_COST); format %{ "sve_reduce_maxL $dst, $src1, $pg, $src2\t# maxL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -3196,8 +3506,7 @@ instruct reduce_maxF_masked_partial(vRegF dst, vRegF src1, vReg src2, pRegGov pg ins_cost(3 * SVE_COST); format %{ "sve_reduce_maxF $dst, $src1, $pg, $src2\t# maxF reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fmaxv(as_FloatRegister($dst$$reg), __ S, @@ -3217,8 +3526,7 @@ instruct reduce_maxD_masked_partial(vRegD dst, vRegD src1, vReg src2, pRegGov pg ins_cost(3 * SVE_COST); format %{ "sve_reduce_maxD $dst, $src1, $pg, $src2\t# maxD reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fmaxv(as_FloatRegister($dst$$reg), __ D, @@ -3277,8 +3585,7 @@ instruct reduce_minI_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vt ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -3296,8 +3603,7 @@ instruct reduce_minL_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_minL $dst, $src1, $src2\t# minL reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -3330,8 +3636,7 @@ instruct reduce_minF_partial(vRegF dst, vRegF src1, vReg src2, effect(TEMP_DEF dst, TEMP ptmp, KILL cr); format %{ "sve_reduce_minF $dst, $src1, $src2\t# minF reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_fminv(as_FloatRegister($dst$$reg), __ S, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); __ fmins(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg)); %} @@ -3363,8 +3668,7 @@ instruct reduce_minD_partial(vRegD dst, vRegD src1, vReg src2, effect(TEMP_DEF dst, TEMP ptmp, KILL cr); format %{ "sve_reduce_minD $dst, $src1, $src2\t# minD reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_fminv(as_FloatRegister($dst$$reg), __ D, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); __ fmind(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg)); %} @@ -3422,8 +3726,7 @@ instruct reduce_minI_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, v ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -3443,8 +3746,7 @@ instruct reduce_minL_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD ins_cost(3 * SVE_COST); format %{ "sve_reduce_minL $dst, $src1, $pg, $src2\t# minL reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -3494,8 +3796,7 @@ instruct reduce_minF_masked_partial(vRegF dst, vRegF src1, vReg src2, pRegGov pg ins_cost(3 * SVE_COST); format %{ "sve_reduce_minF $dst, $src1, $pg, $src2\t# minF reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fminv(as_FloatRegister($dst$$reg), __ S, @@ -3515,8 +3816,7 @@ instruct reduce_minD_masked_partial(vRegD dst, vRegD src1, vReg src2, pRegGov pg ins_cost(3 * SVE_COST); format %{ "sve_reduce_minD $dst, $src1, $pg, $src2\t# minD reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fminv(as_FloatRegister($dst$$reg), __ D, @@ -5074,8 +5374,7 @@ instruct vtest_alltrue_partial(iRegINoSp dst, pRegGov src1, pRegGov src2, pRegGo ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src1); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, - Matcher::vector_length(this, $src1)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src1)); __ sve_eors(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($src1$$reg), as_PRegister($src2$$reg)); __ csetw(as_Register($dst$$reg), Assembler::EQ); @@ -5095,8 +5394,7 @@ instruct vtest_anytrue_partial(iRegINoSp dst, pRegGov src1, pRegGov src2, pRegGo ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src1); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, - Matcher::vector_length(this, $src1)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src1)); __ sve_ands(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($src1$$reg), as_PRegister($src2$$reg)); __ csetw(as_Register($dst$$reg), Assembler::NE); @@ -5331,7 +5629,7 @@ instruct gatherI_partial(vReg dst, indirect mem, vReg idx, pRegGov ptmp, rFlagsR ins_cost(2 * SVE_COST + INSN_COST); format %{ "load_vector_gather $dst, $ptmp, $mem, $idx\t# vector load gather partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); __ sve_ld1w_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); %} @@ -5348,8 +5646,7 @@ instruct gatherL_partial(vReg dst, indirect mem, vReg idx, pRegGov ptmp, rFlagsR ins_cost(3 * SVE_COST + INSN_COST); format %{ "load_vector_gather $dst, $ptmp, $mem, $idx\t# vector load gather partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); __ sve_ld1d_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); @@ -5402,8 +5699,7 @@ instruct gatherI_masked_partial(vReg dst, indirect mem, vReg idx, pRegGov pg, pR ins_cost(3 * SVE_COST); format %{ "load_vector_gather $dst, $pg, $mem, $idx\t# vector load gather predicated partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_ld1w_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), @@ -5422,7 +5718,7 @@ instruct gatherL_masked_partial(vReg dst, indirect mem, vReg idx, pRegGov pg, pR ins_cost(4 * SVE_COST); format %{ "load_vector_gather $dst, $pg, $mem, $idx\t# vector load gather predicated partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); @@ -5477,8 +5773,7 @@ instruct scatterI_partial(indirect mem, vReg src, vReg idx, pRegGov ptmp, rFlags ins_cost(2 * SVE_COST + INSN_COST); format %{ "store_vector_scatter $mem, $ptmp, $idx, $src\t# vector store scatter partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src)); __ sve_st1w_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); %} @@ -5495,8 +5790,7 @@ instruct scatterL_partial(indirect mem, vReg src, vReg idx, pRegGov ptmp, rFlags ins_cost(3 * SVE_COST + INSN_COST); format %{ "store_vector_scatter $mem, $ptmp, $idx, $src\t# vector store scatter partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); __ sve_st1d_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); @@ -5549,8 +5843,7 @@ instruct scatterI_masked_partial(indirect mem, vReg src, vReg idx, pRegGov pg, p ins_cost(3 * SVE_COST); format %{ "store_vector_scatter $mem, $pg, $idx, $src\t# vector store scatter predicated partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_st1w_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), @@ -5569,8 +5862,7 @@ instruct scatterL_masked_partial(indirect mem, vReg src, vReg idx, pRegGov pg, p ins_cost(4 * SVE_COST); format %{ "store_vector_scatter $mem, $pg, $idx, $src\t# vector store scatter predicated partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); @@ -5688,7 +5980,7 @@ instruct vmask_truecount_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg c ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); __ sve_cntp($dst$$Register, size, as_PRegister($ptmp$$reg), as_PRegister($src$$reg)); %} ins_pipe(pipe_slow); @@ -5704,7 +5996,7 @@ instruct vmask_firsttrue_partial(iRegINoSp dst, pReg src, pReg ptmp1, pReg ptmp2 ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp1$$reg), size, + __ sve_ptrue_lanecnt(as_PRegister($ptmp1$$reg), size, Matcher::vector_length(this, $src)); __ sve_brkb(as_PRegister($ptmp2$$reg), as_PRegister($ptmp1$$reg), as_PRegister($src$$reg), false); __ sve_cntp($dst$$Register, size, as_PRegister($ptmp1$$reg), as_PRegister($ptmp2$$reg)); @@ -5722,7 +6014,7 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), ptrue, as_PRegister($ptmp$$reg), as_PRegister($src$$reg)); __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index 874cdf6e4e0c9a36fae4156762f487a1ba657e71..bb757b7d1529a49e8095c6054395a747afcf91af 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -242,12 +242,12 @@ instruct loadV_partial(vReg dst, vmemA mem, pRegGov pgtmp, rFlagsReg cr) %{ match(Set dst (LoadVector mem)); effect(TEMP pgtmp, KILL cr); ins_cost(6 * SVE_COST); - format %{ "sve_whilelo_zr_imm $pgtmp, vector_length\n\t" + format %{ "sve_ptrue $pgtmp, vector_length\n\t" "sve_ldr $dst, $pgtmp, $mem\t# load vector partial" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this)); FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, dst_reg, as_PRegister($pgtmp$$reg), bt, bt, $mem->opcode(), @@ -262,12 +262,12 @@ instruct storeV_partial(vReg src, vmemA mem, pRegGov pgtmp, rFlagsReg cr) %{ match(Set mem (StoreVector mem src)); effect(TEMP pgtmp, KILL cr); ins_cost(5 * SVE_COST); - format %{ "sve_whilelo_zr_imm $pgtmp, vector_length\n\t" + format %{ "sve_ptrue $pgtmp, vector_length\n\t" "sve_str $src, $pgtmp, $mem\t# store vector partial" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this, $src)); FloatRegister src_reg = as_FloatRegister($src$$reg); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, src_reg, as_PRegister($pgtmp$$reg), bt, bt, $mem->opcode(), @@ -302,8 +302,8 @@ instruct loadV_masked_partial(vReg dst, vmemA mem, pRegGov pg, pRegGov pgtmp, rF format %{ "sve_ldr $dst, $pg, $mem\t# load vector predicated partial (sve)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this)); __ sve_and(as_PRegister($pgtmp$$reg), as_PRegister($pgtmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, as_FloatRegister($dst$$reg), @@ -337,8 +337,8 @@ instruct storeV_masked_partial(vReg src, vmemA mem, pRegGov pg, pRegGov pgtmp, r format %{ "sve_str $mem, $pg, $src\t# store vector predicated partial (sve)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ elemType_to_regVariant(bt), + Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($pgtmp$$reg), as_PRegister($pgtmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, as_FloatRegister($src$$reg), @@ -380,7 +380,7 @@ instruct vmaskAll$1(pRegGov dst, ifelse($1, `I', iRegIorL2I, iRegL) src, vReg tm effect(TEMP tmp, KILL cr); ins_cost(3 * SVE_COST); format %{ "sve_dup $tmp, $src\n\t" - "sve_ptrue_lanecnt $dst\n\t" + "sve_ptrue $dst, vector_length\n\t" "sve_cmpne $dst, $dst, $tmp, 0\t# mask all (sve) ($2)" %} ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this); @@ -473,7 +473,7 @@ instruct reinterpretResize(vReg dst, vReg src, pRegGov pgtmp, rFlagsReg cr) %{ length_in_bytes_src : length_in_bytes_dst; assert(length_in_bytes_src <= MaxVectorSize && length_in_bytes_dst <= MaxVectorSize, "invalid vector length"); - __ sve_whilelo_zr_imm(as_PRegister($pgtmp$$reg), __ B, length_in_bytes_resize); + __ sve_ptrue_lanecnt(as_PRegister($pgtmp$$reg), __ B, length_in_bytes_resize); __ sve_dup(as_FloatRegister($dst$$reg), __ B, 0); __ sve_sel(as_FloatRegister($dst$$reg), __ B, as_PRegister($pgtmp$$reg), as_FloatRegister($src$$reg), as_FloatRegister($dst$$reg)); @@ -524,8 +524,10 @@ instruct $1(vReg dst, vReg src) %{ match(Set dst ($2 src)); ins_cost(SVE_COST); format %{ "$4 $dst, $src\t# vector (sve) ($3)" %} - ins_encode %{ - __ $4(as_FloatRegister($dst$$reg), __ $3, + ins_encode %{dnl +ifelse($1, `vnegI', ` + BasicType bt = Matcher::vector_element_basic_type(this);', `') + __ $4(as_FloatRegister($dst$$reg), ifelse($1, `vnegI', `__ elemType_to_regVariant(bt)', `__ $3'), ptrue, as_FloatRegister($src$$reg)); %} ins_pipe(pipe_slow); @@ -548,8 +550,10 @@ instruct $1_masked(vReg dst_src, pRegGov pg) %{ match(Set dst_src ($2 dst_src pg)); ins_cost(SVE_COST); format %{ "$4 $dst_src, $pg, $dst_src\t# vector (sve) ($3)" %} - ins_encode %{ - __ $4(as_FloatRegister($dst_src$$reg), __ $3, + ins_encode %{dnl +ifelse($1, `vnegI', ` + BasicType bt = Matcher::vector_element_basic_type(this);', `') + __ $4(as_FloatRegister($dst_src$$reg), ifelse($1, `vnegI', `__ elemType_to_regVariant(bt)', `__ $3'), as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg)); %} @@ -903,8 +907,8 @@ VMINMAX_PREDICATE(min, MinV, sve_fmin, sve_smin) VMINMAX_PREDICATE(max, MaxV, sve_fmax, sve_smax) dnl -dnl VFMLA($1 $2 $3 ) -dnl VFMLA(name_suffix, size, min_vec_len) +dnl VFMLA($1 $2 ) +dnl VFMLA(name_suffix, size) define(`VFMLA', ` // dst_src1 = dst_src1 + src2 * src3 instruct vfmla$1(vReg dst_src1, vReg src2, vReg src3) %{ @@ -920,15 +924,15 @@ instruct vfmla$1(vReg dst_src1, vReg src2, vReg src3) %{ %}')dnl dnl // vector fmla -VFMLA(F, S, 4) -VFMLA(D, D, 2) +VFMLA(F, S) +VFMLA(D, D) dnl -dnl VFMLA_PREDICATE($1, $2 ) -dnl VFMLA_PREDICATE(type, size) -define(`VFMLA_PREDICATE', ` +dnl VFMAD_PREDICATE($1 $2 ) +dnl VFMAD_PREDICATE(name_suffix, size) +define(`VFMAD_PREDICATE', ` // dst_src1 = dst_src1 * src2 + src3 -instruct vfmla$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ +instruct vfmad$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ predicate(UseFMA && UseSVE > 0); match(Set dst_src1 (FmaV$1 (Binary dst_src1 src2) (Binary src3 pg))); ins_cost(SVE_COST); @@ -940,19 +944,37 @@ instruct vfmla$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ ins_pipe(pipe_slow); %}')dnl dnl -// vector fmla - predicated -VFMLA_PREDICATE(F, S) -VFMLA_PREDICATE(D, D) +// vector fmad - predicated +VFMAD_PREDICATE(F, S) +VFMAD_PREDICATE(D, D) dnl -dnl VFMLS($1 $2 $3 ) -dnl VFMLS(name_suffix, size, min_vec_len) -define(`VFMLS', ` +dnl VFMLS1($1 $2 ) +dnl VFMLS1(name_suffix, size) +define(`VFMLS1', ` // dst_src1 = dst_src1 + -src2 * src3 -// dst_src1 = dst_src1 + src2 * -src3 -instruct vfmls$1(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegV$1 must not be predicated. +instruct vfmls`$1'1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaV$1 dst_src1 (Binary (NegV$1 src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ $2, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +dnl VFMLS2($1 $2 ) +dnl VFMLS2(name_suffix, size) +define(`VFMLS2', ` +// dst_src1 = dst_src1 + src2 * -src3 +// The NegV$1 must not be predicated. +instruct vfmls`$1'2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaV$1 dst_src1 (Binary src2 (NegV$1 src3)))); ins_cost(SVE_COST); format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %} @@ -964,18 +986,63 @@ instruct vfmls$1(vReg dst_src1, vReg src2, vReg src3) %{ %}')dnl dnl // vector fmls -VFMLS(F, S, 4) -VFMLS(D, D, 2) +VFMLS1(F, S) +VFMLS2(F, S) +VFMLS1(D, D) +VFMLS2(D, D) + +dnl +dnl VFMSB_PREDICATE($1 $2 ) +dnl VFMSB_PREDICATE(name_suffix, size) +define(`VFMSB_PREDICATE', ` +// dst_src1 = dst_src1 * -src2 + src3 +// The NegV$1 must not be predicated. +instruct vfmsb$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaV$1 (Binary dst_src1 (NegV$1 src2)) (Binary src3 pg))); + ins_cost(SVE_COST); + format %{ "sve_fmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_fmsb(as_FloatRegister($dst_src1$$reg), __ $2, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +// vector fmsb - predicated +VFMSB_PREDICATE(F, S) +VFMSB_PREDICATE(D, D) dnl -dnl VFNMLA($1 $2 $3 ) -dnl VFNMLA(name_suffix, size, min_vec_len) -define(`VFNMLA', ` +dnl VFNMLA1($1 $2 ) +dnl VFNMLA1(name_suffix, size) +define(`VFNMLA1', ` // dst_src1 = -dst_src1 + -src2 * src3 -// dst_src1 = -dst_src1 + src2 * -src3 -instruct vfnmla$1(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); +// The NegV$1 must not be predicated. +instruct vfnmla`$1'1(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary (NegV$1 src2) src3))); + ins_cost(SVE_COST); + format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ $2, + ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +dnl VFNMLA2($1 $2 ) +dnl VFNMLA2(name_suffix, size) +define(`VFNMLA2', ` +// dst_src1 = -dst_src1 + src2 * -src3 +// The NegV$1 must not be predicated. +instruct vfnmla`$1'2(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(2)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 (NegV$1 src3)))); ins_cost(SVE_COST); format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %} @@ -987,16 +1054,44 @@ instruct vfnmla$1(vReg dst_src1, vReg src2, vReg src3) %{ %}')dnl dnl // vector fnmla -VFNMLA(F, S, 4) -VFNMLA(D, D, 2) +VFNMLA1(F, S) +VFNMLA2(F, S) +VFNMLA1(D, D) +VFNMLA2(D, D) + +dnl +dnl VFNMAD_PREDICATE($1 $2 ) +dnl VFNMAD_PREDICATE(name_suffix, size) +define(`VFNMAD_PREDICATE', ` +// dst_src1 = -src3 + dst_src1 * -src2 +// The NegV$1 must not be predicated. +instruct vfnmad$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->in(2)->as_Vector()->is_predicated_vector() && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaV$1 (Binary dst_src1 (NegV$1 src2)) (Binary (NegV$1 src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmad $dst_src1, $pg, $src2, $src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_fnmad(as_FloatRegister($dst_src1$$reg), __ $2, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +// vector fnmad - predicated +VFNMAD_PREDICATE(F, S) +VFNMAD_PREDICATE(D, D) dnl -dnl VFNMLS($1 $2 $3 ) -dnl VFNMLS(name_suffix, size, min_vec_len) +dnl VFNMLS($1 $2 ) +dnl VFNMLS(name_suffix, size) define(`VFNMLS', ` // dst_src1 = -dst_src1 + src2 * src3 +// The NegV$1 must not be predicated. instruct vfnmls$1(vReg dst_src1, vReg src2, vReg src3) %{ - predicate(UseFMA && UseSVE > 0); + predicate(UseFMA && UseSVE > 0 && + !n->in(1)->as_Vector()->is_predicated_vector()); match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 src3))); ins_cost(SVE_COST); format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %} @@ -1008,12 +1103,35 @@ instruct vfnmls$1(vReg dst_src1, vReg src2, vReg src3) %{ %}')dnl dnl // vector fnmls -VFNMLS(F, S, 4) -VFNMLS(D, D, 2) +VFNMLS(F, S) +VFNMLS(D, D) + +dnl +dnl VFNMSB_PREDICATE($1 $2 ) +dnl VFNMSB_PREDICATE(name_suffix, size) +define(`VFNMSB_PREDICATE', ` +// dst_src1 = -src3 + dst_src1 * src2 +// The NegV$1 must not be predicated. +instruct vfnmsb$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{ + predicate(UseFMA && UseSVE > 0 && + !n->in(2)->in(1)->as_Vector()->is_predicated_vector()); + match(Set dst_src1 (FmaV$1 (Binary dst_src1 src2) (Binary (NegV$1 src3) pg))); + ins_cost(SVE_COST); + format %{ "sve_fnmsb $dst_src1, $pg, $src2, $src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_fnmsb(as_FloatRegister($dst_src1$$reg), __ $2, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +// vector fnmsb - predicated +VFNMSB_PREDICATE(F, S) +VFNMSB_PREDICATE(D, D) dnl -dnl VMLA($1 $2 $3 ) -dnl VMLA(name_suffix, size, min_vec_len) +dnl VMLA($1 $2 ) +dnl VMLA(name_suffix, size) define(`VMLA', ` // dst_src1 = dst_src1 + src2 * src3 instruct vmla$1(vReg dst_src1, vReg src2, vReg src3) @@ -1030,14 +1148,38 @@ instruct vmla$1(vReg dst_src1, vReg src2, vReg src3) %}')dnl dnl // vector mla -VMLA(B, B, 16) -VMLA(S, H, 8) -VMLA(I, S, 4) -VMLA(L, D, 2) +VMLA(B, B) +VMLA(S, H) +VMLA(I, S) +VMLA(L, D) + +dnl +dnl VMLA_PREDICATE($1 $2 ) +dnl VMLA_PREDICATE(name_suffix, size) +define(`VMLA_PREDICATE', ` +// dst_src1 = dst_src1 + src2 * src3 +instruct vmla$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (AddV$1 (Binary dst_src1 (MulV$1 src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mla $dst_src1, $pg, src2, src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_mla(as_FloatRegister($dst_src1$$reg), __ $2, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +// vector mla - predicated +VMLA_PREDICATE(B, B) +VMLA_PREDICATE(S, H) +VMLA_PREDICATE(I, S) +VMLA_PREDICATE(L, D) dnl -dnl VMLS($1 $2 $3 ) -dnl VMLS(name_suffix, size, min_vec_len) +dnl VMLS($1 $2 ) +dnl VMLS(name_suffix, size) define(`VMLS', ` // dst_src1 = dst_src1 - src2 * src3 instruct vmls$1(vReg dst_src1, vReg src2, vReg src3) @@ -1054,10 +1196,34 @@ instruct vmls$1(vReg dst_src1, vReg src2, vReg src3) %}')dnl dnl // vector mls -VMLS(B, B, 16) -VMLS(S, H, 8) -VMLS(I, S, 4) -VMLS(L, D, 2) +VMLS(B, B) +VMLS(S, H) +VMLS(I, S) +VMLS(L, D) + +dnl +dnl VMLS_PREDICATE($1 $2 ) +dnl VMLS_PREDICATE(name_suffix, size) +define(`VMLS_PREDICATE', ` +// dst_src1 = dst_src1 - src2 * src3 +instruct vmls$1_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) +%{ + predicate(UseSVE > 0); + match(Set dst_src1 (SubV$1 (Binary dst_src1 (MulV$1 src2 src3)) pg)); + ins_cost(SVE_COST); + format %{ "sve_mls $dst_src1, $pg, src2, src3\t # vector (sve) ($2)" %} + ins_encode %{ + __ sve_mls(as_FloatRegister($dst_src1$$reg), __ $2, as_PRegister($pg$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl +// vector mls - predicated +VMLS_PREDICATE(B, B) +VMLS_PREDICATE(S, H) +VMLS_PREDICATE(I, S) +VMLS_PREDICATE(L, D) dnl dnl BINARY_OP_TRUE_PREDICATE($1, $2, $3, $4, $5 ) @@ -1091,11 +1257,15 @@ BINARY_OP_PREDICATE(vmulL, MulVL, D, sve_mul) BINARY_OP_PREDICATE(vmulF, MulVF, S, sve_fmul) BINARY_OP_PREDICATE(vmulD, MulVD, D, sve_fmul) -// vector fneg +// vector neg +UNARY_OP_TRUE_PREDICATE(vnegI, NegVI, B/H/S, sve_neg) +UNARY_OP_TRUE_PREDICATE(vnegL, NegVL, D, sve_neg) UNARY_OP_TRUE_PREDICATE(vnegF, NegVF, S, sve_fneg) UNARY_OP_TRUE_PREDICATE(vnegD, NegVD, D, sve_fneg) -// vector fneg - predicated +// vector neg - predicated +UNARY_OP_PREDICATE(vnegI, NegVI, B/H/S, sve_neg) +UNARY_OP_PREDICATE(vnegL, NegVL, D, sve_neg) UNARY_OP_PREDICATE(vnegF, NegVF, S, sve_fneg) UNARY_OP_PREDICATE(vnegD, NegVD, D, sve_fneg) @@ -1254,7 +1424,7 @@ instruct vloadmask_loadV_partial(pRegGov dst, indirect mem, vReg vtmp, pRegGov p // expected vector element type. Convert the vector to predicate. BasicType to_vect_bt = Matcher::vector_element_basic_type(this); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(to_vect_bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), false, as_FloatRegister($vtmp$$reg), as_PRegister($ptmp$$reg), T_BOOLEAN, to_vect_bt, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -1301,7 +1471,7 @@ instruct storeV_vstoremask_partial(indirect mem, pRegGov src, vReg vtmp, BasicType from_vect_bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(from_vect_bt); __ sve_cpy(as_FloatRegister($vtmp$$reg), size, as_PRegister($src$$reg), 1, false); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); loadStoreA_predicated(C2_MacroAssembler(&cbuf), true, as_FloatRegister($vtmp$$reg), as_PRegister($ptmp$$reg), T_BOOLEAN, from_vect_bt, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -1373,8 +1543,7 @@ instruct reduce_$1I_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vtm ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -1398,8 +1567,7 @@ instruct reduce_$1L_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_$1L $dst, $src1, $src2\t# $1L reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -1435,8 +1603,7 @@ instruct reduce_$1_partial($3 src1_dst, vReg src2, pRegGov ptmp, rFlagsReg cr) % effect(TEMP ptmp, KILL cr); format %{ "sve_reduce_$1 $src1_dst, $src1_dst, $src2\t# $1 reduction partial (sve) ($4)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ $4, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ $4, Matcher::vector_length(this, $src2)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ $4, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); %} @@ -1507,8 +1674,7 @@ instruct reduce_$1I_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vR ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -1534,8 +1700,7 @@ instruct reduce_$1L_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD v ins_cost(3 * SVE_COST); format %{ "sve_reduce_$1L $dst, $src1, $pg, $src2\t# $1L reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -1572,8 +1737,7 @@ instruct reduce_$1_masked_partial($3 src1_dst, vReg src2, pRegGov pg, pRegGov pt ins_cost(SVE_COST); format %{ "sve_reduce_$1 $src1_dst, $pg, $src2\t# $1 reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ $4, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ $4, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ $4, @@ -1696,8 +1860,7 @@ instruct reduce_$1I_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD vtm ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -1718,8 +1881,7 @@ instruct reduce_$1L_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD vtmp, ins_cost(2 * SVE_COST); format %{ "sve_reduce_$1L $dst, $src1, $src2\t# $1L reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, $src1$$Register, as_FloatRegister($src2$$reg), as_PRegister($ptmp$$reg), as_FloatRegister($vtmp$$reg)); @@ -1785,8 +1947,7 @@ instruct reduce_$1I_masked_partial(iRegINoSp dst, iRegIorL2I src1, vReg src2, vR ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src2); Assembler::SIMD_RegVariant variant = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), variant, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), variant, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt, @@ -1809,8 +1970,7 @@ instruct reduce_$1L_masked_partial(iRegLNoSp dst, iRegL src1, vReg src2, vRegD v ins_cost(3 * SVE_COST); format %{ "sve_reduce_$1L $dst, $src1, $pg, $src2\t# $1L reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG, @@ -1851,8 +2011,7 @@ instruct reduce_$1$2_partial($5 dst, $5 src1, vReg src2, effect(TEMP_DEF dst, TEMP ptmp, KILL cr); format %{ "sve_reduce_$1$2 $dst, $src1, $src2\t# $1$2 reduction partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ $4, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ $4, Matcher::vector_length(this, $src2)); __ sve_f$1v(as_FloatRegister($dst$$reg), __ $4, as_PRegister($ptmp$$reg), as_FloatRegister($src2$$reg)); __ f`$1'translit($4, `SD', `sd')(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg)); %} @@ -1890,8 +2049,7 @@ instruct reduce_$1$2_masked_partial($5 dst, $5 src1, vReg src2, pRegGov pg, ins_cost(3 * SVE_COST); format %{ "sve_reduce_$1$2 $dst, $src1, $pg, $src2\t# $1$2 reduction predicated partial (sve)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ $4, - Matcher::vector_length(this, $src2)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ $4, Matcher::vector_length(this, $src2)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_f$1v(as_FloatRegister($dst$$reg), __ $4, @@ -2595,8 +2753,7 @@ instruct vtest_$1_partial`'(iRegINoSp dst, pRegGov src1, pRegGov src2, pRegGov p ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src1); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, - Matcher::vector_length(this, $src1)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src1)); __ $3(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($src1$$reg), as_PRegister($src2$$reg)); __ csetw(as_Register($dst$$reg), Assembler::$4); @@ -2818,7 +2975,7 @@ instruct gatherI_partial(vReg dst, indirect mem, vReg idx, pRegGov ptmp, rFlagsR ins_cost(2 * SVE_COST + INSN_COST); format %{ "load_vector_gather $dst, $ptmp, $mem, $idx\t# vector load gather partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); __ sve_ld1w_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); %} @@ -2835,8 +2992,7 @@ instruct gatherL_partial(vReg dst, indirect mem, vReg idx, pRegGov ptmp, rFlagsR ins_cost(3 * SVE_COST + INSN_COST); format %{ "load_vector_gather $dst, $ptmp, $mem, $idx\t# vector load gather partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); __ sve_ld1d_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); @@ -2889,8 +3045,7 @@ instruct gatherI_masked_partial(vReg dst, indirect mem, vReg idx, pRegGov pg, pR ins_cost(3 * SVE_COST); format %{ "load_vector_gather $dst, $pg, $mem, $idx\t# vector load gather predicated partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_ld1w_gather(as_FloatRegister($dst$$reg), as_PRegister($ptmp$$reg), @@ -2909,7 +3064,7 @@ instruct gatherL_masked_partial(vReg dst, indirect mem, vReg idx, pRegGov pg, pR ins_cost(4 * SVE_COST); format %{ "load_vector_gather $dst, $pg, $mem, $idx\t# vector load gather predicated partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); @@ -2964,8 +3119,7 @@ instruct scatterI_partial(indirect mem, vReg src, vReg idx, pRegGov ptmp, rFlags ins_cost(2 * SVE_COST + INSN_COST); format %{ "store_vector_scatter $mem, $ptmp, $idx, $src\t# vector store scatter partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src)); __ sve_st1w_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); %} @@ -2982,8 +3136,7 @@ instruct scatterL_partial(indirect mem, vReg src, vReg idx, pRegGov ptmp, rFlags ins_cost(3 * SVE_COST + INSN_COST); format %{ "store_vector_scatter $mem, $ptmp, $idx, $src\t# vector store scatter partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); __ sve_st1d_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), as_Register($mem$$base), as_FloatRegister($idx$$reg)); @@ -3036,8 +3189,7 @@ instruct scatterI_masked_partial(indirect mem, vReg src, vReg idx, pRegGov pg, p ins_cost(3 * SVE_COST); format %{ "store_vector_scatter $mem, $pg, $idx, $src\t# vector store scatter predicated partial (S)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ S, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ S, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_st1w_scatter(as_FloatRegister($src$$reg), as_PRegister($ptmp$$reg), @@ -3056,8 +3208,7 @@ instruct scatterL_masked_partial(indirect mem, vReg src, vReg idx, pRegGov pg, p ins_cost(4 * SVE_COST); format %{ "store_vector_scatter $mem, $pg, $idx, $src\t# vector store scatter predicated partial (D)" %} ins_encode %{ - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), __ D, - Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), __ D, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg), as_PRegister($pg$$reg), as_PRegister($pg$$reg)); __ sve_uunpklo(as_FloatRegister($idx$$reg), __ D, as_FloatRegister($idx$$reg)); @@ -3161,7 +3312,7 @@ instruct vmask_truecount_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg c ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); __ sve_cntp($dst$$Register, size, as_PRegister($ptmp$$reg), as_PRegister($src$$reg)); %} ins_pipe(pipe_slow); @@ -3177,7 +3328,7 @@ instruct vmask_firsttrue_partial(iRegINoSp dst, pReg src, pReg ptmp1, pReg ptmp2 ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp1$$reg), size, + __ sve_ptrue_lanecnt(as_PRegister($ptmp1$$reg), size, Matcher::vector_length(this, $src)); __ sve_brkb(as_PRegister($ptmp2$$reg), as_PRegister($ptmp1$$reg), as_PRegister($src$$reg), false); __ sve_cntp($dst$$Register, size, as_PRegister($ptmp1$$reg), as_PRegister($ptmp2$$reg)); @@ -3195,7 +3346,7 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr ins_encode %{ BasicType bt = Matcher::vector_element_basic_type(this, $src); Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); - __ sve_whilelo_zr_imm(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); + __ sve_ptrue_lanecnt(as_PRegister($ptmp$$reg), size, Matcher::vector_length(this, $src)); __ sve_and(as_PRegister($ptmp$$reg), ptrue, as_PRegister($ptmp$$reg), as_PRegister($src$$reg)); __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 10fcdaa243c006afdb3e5ebc9e21a51f6970c2b4..448648d8d80038b5b6f439d45f3ddb77b7c1b3cf 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -3173,8 +3173,11 @@ public: INSN(sve_fnmla, 0b01100101, 1, 0b010); // floating-point negated fused multiply-add: Zda = -Zda + -Zn * Zm INSN(sve_fnmls, 0b01100101, 1, 0b011); // floating-point negated fused multiply-subtract: Zda = -Zda + Zn * Zm INSN(sve_fmad, 0b01100101, 1, 0b100); // floating-point fused multiply-add, writing multiplicand: Zda = Zm + Zda * Zn - INSN(sve_mla, 0b00000100, 0, 0b010); // multiply-add: Zda = Zda + Zn*Zm - INSN(sve_mls, 0b00000100, 0, 0b011); // multiply-subtract: Zda = Zda + -Zn*Zm + INSN(sve_fmsb, 0b01100101, 1, 0b101); // floating-point fused multiply-subtract, writing multiplicand: Zda = Zm + -Zda * Zn + INSN(sve_fnmad, 0b01100101, 1, 0b110); // floating-point negated fused multiply-add, writing multiplicand: Zda = -Zm + -Zda * Zn + INSN(sve_fnmsb, 0b01100101, 1, 0b111); // floating-point negated fused multiply-subtract, writing multiplicand: Zda = -Zm + Zda * Zn + INSN(sve_mla, 0b00000100, 0, 0b010); // multiply-add, writing addend: Zda = Zda + Zn*Zm + INSN(sve_mls, 0b00000100, 0, 0b011); // multiply-subtract, writing addend: Zda = Zda + -Zn*Zm #undef INSN // SVE bitwise logical - unpredicated diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 6f91b1539a6df7e336f455970a23db93db446711..b7e6ccc28d98b3384423eb5bac462eac223f4cb1 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1582,7 +1582,9 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { } -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on aarch64"); Assembler::Condition acond, ncond; switch (condition) { diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index e31fa7df08047065a3e6f028efd91908ef547713..44eebc538b63a300b6775f8bfab304ea019d740e 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,14 +91,6 @@ // in the range of [0, lane_cnt), or to false otherwise. void sve_ptrue_lanecnt(PRegister dst, SIMD_RegVariant size, int lane_cnt); - // Generate predicate through whilelo, by comparing ZR with an unsigned - // immediate. rscratch1 will be clobbered. - inline void sve_whilelo_zr_imm(PRegister pd, SIMD_RegVariant size, uint imm) { - assert(UseSVE > 0, "not supported"); - mov(rscratch1, imm); - sve_whilelo(pd, size, zr, rscratch1); - } - // Extract a scalar element from an sve vector at position 'idx'. // rscratch1 will be clobbered. // T could be FloatRegister or Register. 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/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 80287fb6949cc797e6dd1284f6c5d9848219c230..ad1a6d58596ff0e08ca6f1f9b188007fad252227 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2543,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; @@ -2553,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. @@ -2575,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, @@ -4339,16 +4339,17 @@ void MacroAssembler::remove_frame(int framesize) { } -// 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 @@ -4367,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); @@ -4388,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); @@ -4399,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); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 29d4b8ac119e6319db8d383e05a90dd256fdea28..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); } @@ -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/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/relocInfo_aarch64.hpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp index 7708b4423e04843f64d36074c8fbc9f012f3bb85..904fe0814274481b99fab7e40702a6334376cc62 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp @@ -29,8 +29,9 @@ // machine-dependent parts of class relocInfo private: enum { - // Relocations are byte-aligned. - offset_unit = 1, + // AArch64 instructions are always 4 bytes long and 4-aligned, so + // the two lowest offset bits can always be discarded. + offset_unit = 4, // Must be at least 1 for RelocInfo::narrow_oop_in_const. format_width = 1 }; diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index eef7e6afe71ebac1a2dc98af7ec3729d365291a5..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, + 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,31 +4791,36 @@ 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); + // difference result - len is the count of guaranteed to be + // positive bytes + + __ 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); - __ bind(RET_TRUE_NO_POP); __ leave(); - __ mov(result, 1); + __ sub(result, result, len); __ ret(lr); return entry; @@ -6621,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; @@ -7515,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 ae48d8788e182f4446a80b91a40c6f2a0f3e5372..a17e7540e42d24eac8f2db642c7d1f0c407b75ba 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -76,8 +76,8 @@ class aarch64 { public: - static address _has_negatives; - static address _has_negatives_long; + static address _count_positives; + static address _count_positives_long; static address get_previous_sp_entry() { @@ -132,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 bf0a4e4472927e33b12b18c2ea8a310b665c3758..2df88c2d069615efd26d60f848160c52bda16a74 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1064,18 +1064,47 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract } void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { - // Bang each page in the shadow zone. We can't assume it's been done for - // an interpreter frame with greater than a page of locals, so each page - // needs to be checked. Only true for non-native. - const int n_shadow_pages = (int)(StackOverflow::stack_shadow_zone_size() / os::vm_page_size()); - const int start_page = native_call ? n_shadow_pages : 1; + // See more discussion in stackOverflow.hpp. + + const int shadow_zone_size = checked_cast(StackOverflow::stack_shadow_zone_size()); const int page_size = os::vm_page_size(); - for (int pages = start_page; pages <= n_shadow_pages ; pages++) { - __ sub(rscratch2, sp, pages*page_size); + const int n_shadow_pages = shadow_zone_size / page_size; + +#ifdef ASSERT + Label L_good_limit; + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_safe_limit())); + __ cbnz(rscratch1, L_good_limit); + __ stop("shadow zone safe limit is not initialized"); + __ bind(L_good_limit); + + Label L_good_watermark; + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark())); + __ cbnz(rscratch1, L_good_watermark); + __ stop("shadow zone growth watermark is not initialized"); + __ bind(L_good_watermark); +#endif + + Label L_done; + + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark())); + __ cmp(sp, rscratch1); + __ br(Assembler::HI, L_done); + + for (int p = 1; p <= n_shadow_pages; p++) { + __ sub(rscratch2, sp, p*page_size); __ str(zr, Address(rscratch2)); } -} + // Record the new watermark, but only if the update is above the safe limit. + // Otherwise, the next time around the check above would pass the safe limit. + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_safe_limit())); + __ cmp(sp, rscratch1); + __ br(Assembler::LS, L_done); + __ mov(rscratch1, sp); + __ str(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark())); + + __ bind(L_done); +} // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index f7ffe84618d1c59c6646a753047f27c29740392c..b92167fb6a0304a5cf7a5720be6159b9c634a685 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.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 @@ -1412,7 +1412,10 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { } -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on arm"); + AsmCondition acond = al; AsmCondition ncond = nv; if (opr1 != opr2) { 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/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index b04c49152f3fb81e72a721c61d6592549f208669..730e95ae775ae288cf10d120e150bd43e35a0660 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.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. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1547,8 +1547,10 @@ inline void load_to_reg(LIR_Assembler *lasm, LIR_Opr src, LIR_Opr dst) { } } +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on ppc"); -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { if (opr1->is_equal(opr2) || opr1->is_same_register(opr2)) { load_to_reg(this, opr1, result); // Condition doesn't matter. return; 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/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/riscv/abstractInterpreter_riscv.cpp b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31c63abe71d1a6c480860779e05588dfde4c6c89 --- /dev/null +++ b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "interpreter/interpreter.hpp" +#include "oops/constMethod.hpp" +#include "oops/klass.inline.hpp" +#include "oops/method.hpp" +#include "runtime/frame.inline.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" +#include "utilities/macros.hpp" + +int AbstractInterpreter::BasicType_as_index(BasicType type) { + int i = 0; + switch (type) { + case T_BOOLEAN: i = 0; break; + case T_CHAR : i = 1; break; + case T_BYTE : i = 2; break; + case T_SHORT : i = 3; break; + case T_INT : i = 4; break; + case T_LONG : i = 5; break; + case T_VOID : i = 6; break; + case T_FLOAT : i = 7; break; + case T_DOUBLE : i = 8; break; + case T_OBJECT : i = 9; break; + case T_ARRAY : i = 9; break; + default : ShouldNotReachHere(); + } + assert(0 <= i && i < AbstractInterpreter::number_of_result_handlers, + "index out of bounds"); + return i; +} + +// How much stack a method activation needs in words. +int AbstractInterpreter::size_top_interpreter_activation(Method* method) { + const int entry_size = frame::interpreter_frame_monitor_size(); + + // total overhead size: entry_size + (saved fp thru expr stack + // bottom). be sure to change this if you add/subtract anything + // to/from the overhead area + const int overhead_size = + -(frame::interpreter_frame_initial_sp_offset) + entry_size; + + const int stub_code = frame::entry_frame_after_call_words; + assert_cond(method != NULL); + const int method_stack = (method->max_locals() + method->max_stack()) * + Interpreter::stackElementWords; + return (overhead_size + method_stack + stub_code); +} + +// asm based interpreter deoptimization helpers +int AbstractInterpreter::size_activation(int max_stack, + int temps, + int extra_args, + int monitors, + int callee_params, + int callee_locals, + bool is_top_frame) { + // Note: This calculation must exactly parallel the frame setup + // in TemplateInterpreterGenerator::generate_method_entry. + + // fixed size of an interpreter frame: + int overhead = frame::sender_sp_offset - + frame::interpreter_frame_initial_sp_offset; + // Our locals were accounted for by the caller (or last_frame_adjust + // on the transistion) Since the callee parameters already account + // for the callee's params we only need to account for the extra + // locals. + int size = overhead + + (callee_locals - callee_params) + + monitors * frame::interpreter_frame_monitor_size() + + // On the top frame, at all times SP <= ESP, and SP is + // 16-aligned. We ensure this by adjusting SP on method + // entry and re-entry to allow room for the maximum size of + // the expression stack. When we call another method we bump + // SP so that no stack space is wasted. So, only on the top + // frame do we need to allow max_stack words. + (is_top_frame ? max_stack : temps + extra_args); + + // On riscv we always keep the stack pointer 16-aligned, so we + // must round up here. + size = align_up(size, 2); + + return size; +} + +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_locals, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + // The frame interpreter_frame is guaranteed to be the right size, + // as determined by a previous call to the size_activation() method. + // It is also guaranteed to be walkable even though it is in a + // skeletal state + assert_cond(method != NULL && caller != NULL && interpreter_frame != NULL); + int max_locals = method->max_locals() * Interpreter::stackElementWords; + int extra_locals = (method->max_locals() - method->size_of_parameters()) * + Interpreter::stackElementWords; + +#ifdef ASSERT + assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable"); +#endif + + interpreter_frame->interpreter_frame_set_method(method); + // NOTE the difference in using sender_sp and interpreter_frame_sender_sp + // interpreter_frame_sender_sp is the original sp of the caller (the unextended_sp) + // and sender_sp is fp + intptr_t* locals = NULL; + if (caller->is_interpreted_frame()) { + locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1; + } else { + locals = interpreter_frame->sender_sp() + max_locals - 1; + } + +#ifdef ASSERT + if (caller->is_interpreted_frame()) { + assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); + } +#endif + + interpreter_frame->interpreter_frame_set_locals(locals); + BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); + BasicObjectLock* monbot = montop - moncount; + interpreter_frame->interpreter_frame_set_monitor_end(monbot); + + // Set last_sp + intptr_t* last_sp = (intptr_t*) monbot - + tempcount*Interpreter::stackElementWords - + popframe_extra_args; + interpreter_frame->interpreter_frame_set_last_sp(last_sp); + + // All frames but the initial (oldest) interpreter frame we fill in have + // a value for sender_sp that allows walking the stack but isn't + // truly correct. Correct the value here. + if (extra_locals != 0 && + interpreter_frame->sender_sp() == + interpreter_frame->interpreter_frame_sender_sp()) { + interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + + extra_locals); + } + + *interpreter_frame->interpreter_frame_cache_addr() = + method->constants()->cache(); + *interpreter_frame->interpreter_frame_mirror_addr() = + method->method_holder()->java_mirror(); +} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f15ef5304c515adfddc24f80c73572159ccf6957 --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp @@ -0,0 +1,372 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/sharedRuntime.hpp" + +int AbstractAssembler::code_fill_byte() { + return 0; +} + +void Assembler::add(Register Rd, Register Rn, int64_t increment, Register temp) { + if (is_imm_in_range(increment, 12, 0)) { + addi(Rd, Rn, increment); + } else { + assert_different_registers(Rn, temp); + li(temp, increment); + add(Rd, Rn, temp); + } +} + +void Assembler::addw(Register Rd, Register Rn, int64_t increment, Register temp) { + if (is_imm_in_range(increment, 12, 0)) { + addiw(Rd, Rn, increment); + } else { + assert_different_registers(Rn, temp); + li(temp, increment); + addw(Rd, Rn, temp); + } +} + +void Assembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) { + if (is_imm_in_range(-decrement, 12, 0)) { + addi(Rd, Rn, -decrement); + } else { + assert_different_registers(Rn, temp); + li(temp, decrement); + sub(Rd, Rn, temp); + } +} + +void Assembler::subw(Register Rd, Register Rn, int64_t decrement, Register temp) { + if (is_imm_in_range(-decrement, 12, 0)) { + addiw(Rd, Rn, -decrement); + } else { + assert_different_registers(Rn, temp); + li(temp, decrement); + subw(Rd, Rn, temp); + } +} + +void Assembler::zext_w(Register Rd, Register Rs) { + add_uw(Rd, Rs, zr); +} + +void Assembler::_li(Register Rd, int64_t imm) { + // int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff + int shift = 12; + int64_t upper = imm, lower = imm; + // Split imm to a lower 12-bit sign-extended part and the remainder, + // because addi will sign-extend the lower imm. + lower = ((int32_t)imm << 20) >> 20; + upper -= lower; + + // Test whether imm is a 32-bit integer. + if (!(((imm) & ~(int64_t)0x7fffffff) == 0 || + (((imm) & ~(int64_t)0x7fffffff) == ~(int64_t)0x7fffffff))) { + while (((upper >> shift) & 1) == 0) { shift++; } + upper >>= shift; + li(Rd, upper); + slli(Rd, Rd, shift); + if (lower != 0) { + addi(Rd, Rd, lower); + } + } else { + // 32-bit integer + Register hi_Rd = zr; + if (upper != 0) { + lui(Rd, (int32_t)upper); + hi_Rd = Rd; + } + if (lower != 0 || hi_Rd == zr) { + addiw(Rd, hi_Rd, lower); + } + } +} + +void Assembler::li64(Register Rd, int64_t imm) { + // Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or + // (imm[31:28] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1. + int64_t lower = imm & 0xffffffff; + lower -= ((lower << 44) >> 44); + int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower; + int32_t upper = (tmp_imm - (int32_t)lower) >> 32; + + // Load upper 32 bits + int64_t up = upper, lo = upper; + lo = (lo << 52) >> 52; + up -= lo; + up = (int32_t)up; + lui(Rd, up); + addi(Rd, Rd, lo); + + // Load the rest 32 bits. + slli(Rd, Rd, 12); + addi(Rd, Rd, (int32_t)lower >> 20); + slli(Rd, Rd, 12); + lower = ((int32_t)imm << 12) >> 20; + addi(Rd, Rd, lower); + slli(Rd, Rd, 8); + lower = imm & 0xff; + addi(Rd, Rd, lower); +} + +void Assembler::li32(Register Rd, int32_t imm) { + // int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit + int64_t upper = imm, lower = imm; + lower = (imm << 20) >> 20; + upper -= lower; + upper = (int32_t)upper; + // lui Rd, imm[31:12] + imm[11] + lui(Rd, upper); + // use addiw to distinguish li32 to li64 + addiw(Rd, Rd, lower); +} + +#define INSN(NAME, REGISTER) \ + void Assembler::NAME(const address &dest, Register temp) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_imm_in_range(distance, 20, 1)) { \ + jal(REGISTER, distance); \ + } else { \ + assert(temp != noreg, "temp must not be empty register!"); \ + int32_t offset = 0; \ + movptr_with_offset(temp, dest, offset); \ + jalr(REGISTER, temp, offset); \ + } \ + } \ + void Assembler::NAME(Label &l, Register temp) { \ + jal(REGISTER, l, temp); \ + } \ + + INSN(j, x0); + INSN(jal, x1); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + void Assembler::NAME(Register Rs) { \ + jalr(REGISTER, Rs, 0); \ + } + + INSN(jr, x0); + INSN(jalr, x1); + +#undef INSN + +void Assembler::ret() { + jalr(x0, x1, 0); +} + +#define INSN(NAME, REGISTER) \ + void Assembler::NAME(const address &dest, Register temp) { \ + assert_cond(dest != NULL); \ + assert(temp != noreg, "temp must not be empty register!"); \ + int64_t distance = dest - pc(); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, distance + 0x800); \ + jalr(REGISTER, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr_with_offset(temp, dest, offset); \ + jalr(REGISTER, temp, offset); \ + } \ + } + + INSN(call, x1); + INSN(tail, x0); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + void Assembler::NAME(const Address &adr, Register temp) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + code_section()->relocate(pc(), adr.rspec()); \ + NAME(adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + int32_t offset = 0; \ + baseOffset(temp, adr, offset); \ + jalr(REGISTER, temp, offset); \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(j, x0); + INSN(jal, x1); + INSN(call, x1); + INSN(tail, x0); + +#undef INSN + +void Assembler::wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn, + compare_and_branch_label_insn neg_insn, bool is_far) { + if (is_far) { + Label done; + (this->*neg_insn)(r1, r2, done, /* is_far */ false); + j(L); + bind(done); + } else { + if (L.is_bound()) { + (this->*insn)(r1, r2, target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(r1, r2, pc()); + } + } +} + +void Assembler::wrap_label(Register Rt, Label &L, Register tmp, load_insn_by_temp insn) { + if (L.is_bound()) { + (this->*insn)(Rt, target(L), tmp); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(Rt, pc(), tmp); + } +} + +void Assembler::wrap_label(Register Rt, Label &L, jal_jalr_insn insn) { + if (L.is_bound()) { + (this->*insn)(Rt, target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(Rt, pc()); + } +} + +void Assembler::movptr_with_offset(Register Rd, address addr, int32_t &offset) { + uintptr_t imm64 = (uintptr_t)addr; +#ifndef PRODUCT + { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64); + block_comment(buffer); + } +#endif + assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (uintptr_t)-1), + "48-bit overflow in address constant"); + // Load upper 32 bits + int32_t imm = imm64 >> 16; + int64_t upper = imm, lower = imm; + lower = (lower << 52) >> 52; + upper -= lower; + upper = (int32_t)upper; + lui(Rd, upper); + addi(Rd, Rd, lower); + + // Load the rest 16 bits. + slli(Rd, Rd, 11); + addi(Rd, Rd, (imm64 >> 5) & 0x7ff); + slli(Rd, Rd, 5); + + // This offset will be used by following jalr/ld. + offset = imm64 & 0x1f; +} + +void Assembler::movptr(Register Rd, uintptr_t imm64) { + movptr(Rd, (address)imm64); +} + +void Assembler::movptr(Register Rd, address addr) { + int offset = 0; + movptr_with_offset(Rd, addr, offset); + addi(Rd, Rd, offset); +} + +void Assembler::ifence() { + fence_i(); + if (UseConservativeFence) { + fence(ir, ir); + } +} + +#define INSN(NAME, NEG_INSN) \ + void Assembler::NAME(Register Rs, Register Rt, const address &dest) { \ + NEG_INSN(Rt, Rs, dest); \ + } \ + void Assembler::NAME(Register Rs, Register Rt, Label &l, bool is_far) { \ + NEG_INSN(Rt, Rs, l, is_far); \ + } + + INSN(bgt, blt); + INSN(ble, bge); + INSN(bgtu, bltu); + INSN(bleu, bgeu); +#undef INSN + +#undef __ + +Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) { + _target = target; + switch (rtype) { + case relocInfo::oop_type: + case relocInfo::metadata_type: + // Oops are a special case. Normally they would be their own section + // but in cases like icBuffer they are literals in the code stream that + // we don't have a section for. We use none so that we get a literal address + // which is always patchable. + break; + case relocInfo::external_word_type: + _rspec = external_word_Relocation::spec(target); + break; + case relocInfo::internal_word_type: + _rspec = internal_word_Relocation::spec(target); + break; + case relocInfo::opt_virtual_call_type: + _rspec = opt_virtual_call_Relocation::spec(); + break; + case relocInfo::static_call_type: + _rspec = static_call_Relocation::spec(); + break; + case relocInfo::runtime_call_type: + _rspec = runtime_call_Relocation::spec(); + break; + case relocInfo::poll_type: + case relocInfo::poll_return_type: + _rspec = Relocation::spec_simple(rtype); + break; + case relocInfo::none: + _rspec = RelocationHolder::none; + break; + default: + ShouldNotReachHere(); + } +} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c1e7b1c54c279d3c8a2fdb4353a66895cf4f4971 --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -0,0 +1,3048 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_ASSEMBLER_RISCV_HPP +#define CPU_RISCV_ASSEMBLER_RISCV_HPP + +#include "asm/register.hpp" +#include "assembler_riscv.inline.hpp" +#include "metaprogramming/enableIf.hpp" + +#define XLEN 64 + +// definitions of various symbolic names for machine registers + +// First intercalls between C and Java which use 8 general registers +// and 8 floating registers + +class Argument { + public: + enum { + n_int_register_parameters_c = 8, // x10, x11, ... x17 (c_rarg0, c_rarg1, ...) + n_float_register_parameters_c = 8, // f10, f11, ... f17 (c_farg0, c_farg1, ... ) + + n_int_register_parameters_j = 8, // x11, ... x17, x10 (j_rarg0, j_rarg1, ...) + n_float_register_parameters_j = 8 // f10, f11, ... f17 (j_farg0, j_farg1, ...) + }; +}; + +// function argument(caller-save registers) +REGISTER_DECLARATION(Register, c_rarg0, x10); +REGISTER_DECLARATION(Register, c_rarg1, x11); +REGISTER_DECLARATION(Register, c_rarg2, x12); +REGISTER_DECLARATION(Register, c_rarg3, x13); +REGISTER_DECLARATION(Register, c_rarg4, x14); +REGISTER_DECLARATION(Register, c_rarg5, x15); +REGISTER_DECLARATION(Register, c_rarg6, x16); +REGISTER_DECLARATION(Register, c_rarg7, x17); + +REGISTER_DECLARATION(FloatRegister, c_farg0, f10); +REGISTER_DECLARATION(FloatRegister, c_farg1, f11); +REGISTER_DECLARATION(FloatRegister, c_farg2, f12); +REGISTER_DECLARATION(FloatRegister, c_farg3, f13); +REGISTER_DECLARATION(FloatRegister, c_farg4, f14); +REGISTER_DECLARATION(FloatRegister, c_farg5, f15); +REGISTER_DECLARATION(FloatRegister, c_farg6, f16); +REGISTER_DECLARATION(FloatRegister, c_farg7, f17); + +// Symbolically name the register arguments used by the Java calling convention. +// We have control over the convention for java so we can do what we please. +// What pleases us is to offset the java calling convention so that when +// we call a suitable jni method the arguments are lined up and we don't +// have to do much shuffling. A suitable jni method is non-static and a +// small number of arguments. +// +// |------------------------------------------------------------------------| +// | c_rarg0 c_rarg1 c_rarg2 c_rarg3 c_rarg4 c_rarg5 c_rarg6 c_rarg7 | +// |------------------------------------------------------------------------| +// | x10 x11 x12 x13 x14 x15 x16 x17 | +// |------------------------------------------------------------------------| +// | j_rarg7 j_rarg0 j_rarg1 j_rarg2 j_rarg3 j_rarg4 j_rarg5 j_rarg6 | +// |------------------------------------------------------------------------| + +REGISTER_DECLARATION(Register, j_rarg0, c_rarg1); +REGISTER_DECLARATION(Register, j_rarg1, c_rarg2); +REGISTER_DECLARATION(Register, j_rarg2, c_rarg3); +REGISTER_DECLARATION(Register, j_rarg3, c_rarg4); +REGISTER_DECLARATION(Register, j_rarg4, c_rarg5); +REGISTER_DECLARATION(Register, j_rarg5, c_rarg6); +REGISTER_DECLARATION(Register, j_rarg6, c_rarg7); +REGISTER_DECLARATION(Register, j_rarg7, c_rarg0); + +// Java floating args are passed as per C + +REGISTER_DECLARATION(FloatRegister, j_farg0, f10); +REGISTER_DECLARATION(FloatRegister, j_farg1, f11); +REGISTER_DECLARATION(FloatRegister, j_farg2, f12); +REGISTER_DECLARATION(FloatRegister, j_farg3, f13); +REGISTER_DECLARATION(FloatRegister, j_farg4, f14); +REGISTER_DECLARATION(FloatRegister, j_farg5, f15); +REGISTER_DECLARATION(FloatRegister, j_farg6, f16); +REGISTER_DECLARATION(FloatRegister, j_farg7, f17); + +// zero rigster +REGISTER_DECLARATION(Register, zr, x0); +// global pointer +REGISTER_DECLARATION(Register, gp, x3); +// thread pointer +REGISTER_DECLARATION(Register, tp, x4); + +// registers used to hold VM data either temporarily within a method +// or across method calls + +// volatile (caller-save) registers + +// current method -- must be in a call-clobbered register +REGISTER_DECLARATION(Register, xmethod, x31); +// return address +REGISTER_DECLARATION(Register, ra, x1); + +// non-volatile (callee-save) registers + +// stack pointer +REGISTER_DECLARATION(Register, sp, x2); +// frame pointer +REGISTER_DECLARATION(Register, fp, x8); +// base of heap +REGISTER_DECLARATION(Register, xheapbase, x27); +// constant pool cache +REGISTER_DECLARATION(Register, xcpool, x26); +// monitors allocated on stack +REGISTER_DECLARATION(Register, xmonitors, x25); +// locals on stack +REGISTER_DECLARATION(Register, xlocals, x24); + +// java thread pointer +REGISTER_DECLARATION(Register, xthread, x23); +// bytecode pointer +REGISTER_DECLARATION(Register, xbcp, x22); +// Dispatch table base +REGISTER_DECLARATION(Register, xdispatch, x21); +// Java stack pointer +REGISTER_DECLARATION(Register, esp, x20); + +// temporary register(caller-save registers) +REGISTER_DECLARATION(Register, t0, x5); +REGISTER_DECLARATION(Register, t1, x6); +REGISTER_DECLARATION(Register, t2, x7); + +const Register g_INTArgReg[Argument::n_int_register_parameters_c] = { + c_rarg0, c_rarg1, c_rarg2, c_rarg3, c_rarg4, c_rarg5, c_rarg6, c_rarg7 +}; + +const FloatRegister g_FPArgReg[Argument::n_float_register_parameters_c] = { + c_farg0, c_farg1, c_farg2, c_farg3, c_farg4, c_farg5, c_farg6, c_farg7 +}; + +#define assert_cond(ARG1) assert(ARG1, #ARG1) + +// Addressing modes +class Address { + public: + + enum mode { no_mode, base_plus_offset, pcrel, literal }; + + private: + Register _base; + Register _index; + int64_t _offset; + enum mode _mode; + + RelocationHolder _rspec; + + // If the target is far we'll need to load the ea of this to a + // register to reach it. Otherwise if near we can do PC-relative + // addressing. + address _target; + + public: + Address() + : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } + Address(Register r) + : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } + + template::value)> + Address(Register r, T o) + : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) {} + + Address(Register r, ByteSize disp) + : Address(r, in_bytes(disp)) {} + Address(address target, RelocationHolder const& rspec) + : _base(noreg), + _index(noreg), + _offset(0), + _mode(literal), + _rspec(rspec), + _target(target) { } + Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type); + + const Register base() const { + guarantee((_mode == base_plus_offset | _mode == pcrel | _mode == literal), "wrong mode"); + return _base; + } + long offset() const { + return _offset; + } + Register index() const { + return _index; + } + mode getMode() const { + return _mode; + } + + bool uses(Register reg) const { return _base == reg; } + const address target() const { return _target; } + const RelocationHolder& rspec() const { return _rspec; } + ~Address() { + _target = NULL; + _base = NULL; + } +}; + +// Convience classes +class RuntimeAddress: public Address { + + public: + + RuntimeAddress(address target) : Address(target, relocInfo::runtime_call_type) {} + ~RuntimeAddress() {} +}; + +class OopAddress: public Address { + + public: + + OopAddress(address target) : Address(target, relocInfo::oop_type) {} + ~OopAddress() {} +}; + +class ExternalAddress: public Address { + private: + static relocInfo::relocType reloc_for_target(address target) { + // Sometimes ExternalAddress is used for values which aren't + // exactly addresses, like the card table base. + // external_word_type can't be used for values in the first page + // so just skip the reloc in that case. + return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none; + } + + public: + + ExternalAddress(address target) : Address(target, reloc_for_target(target)) {} + ~ExternalAddress() {} +}; + +class InternalAddress: public Address { + + public: + + InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {} + ~InternalAddress() {} +}; + +class Assembler : public AbstractAssembler { +public: + + enum { instruction_size = 4 }; + + //---< calculate length of instruction >--- + // We just use the values set above. + // instruction must start at passed address + static unsigned int instr_len(unsigned char *instr) { return instruction_size; } + + //---< longest instructions >--- + static unsigned int instr_maxlen() { return instruction_size; } + + enum RoundingMode { + rne = 0b000, // round to Nearest, ties to Even + rtz = 0b001, // round towards Zero + rdn = 0b010, // round Down (towards eegative infinity) + rup = 0b011, // round Up (towards infinity) + rmm = 0b100, // round to Nearest, ties to Max Magnitude + rdy = 0b111, // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid. + }; + + void baseOffset32(Register Rd, const Address &adr, int32_t &offset) { + assert(Rd != noreg, "Rd must not be empty register!"); + guarantee(Rd != adr.base(), "should use different registers!"); + if (is_offset_in_range(adr.offset(), 32)) { + int32_t imm = adr.offset(); + int32_t upper = imm, lower = imm; + lower = (imm << 20) >> 20; + upper -= lower; + lui(Rd, upper); + offset = lower; + } else { + movptr_with_offset(Rd, (address)(uintptr_t)adr.offset(), offset); + } + add(Rd, Rd, adr.base()); + } + + void baseOffset(Register Rd, const Address &adr, int32_t &offset) { + if (is_offset_in_range(adr.offset(), 12)) { + assert(Rd != noreg, "Rd must not be empty register!"); + addi(Rd, adr.base(), adr.offset()); + offset = 0; + } else { + baseOffset32(Rd, adr, offset); + } + } + + void _li(Register Rd, int64_t imm); // optimized load immediate + void li32(Register Rd, int32_t imm); + void li64(Register Rd, int64_t imm); + void movptr(Register Rd, address addr); + void movptr_with_offset(Register Rd, address addr, int32_t &offset); + void movptr(Register Rd, uintptr_t imm64); + void ifence(); + void j(const address &dest, Register temp = t0); + void j(const Address &adr, Register temp = t0); + void j(Label &l, Register temp = t0); + void jal(Label &l, Register temp = t0); + void jal(const address &dest, Register temp = t0); + void jal(const Address &adr, Register temp = t0); + void jr(Register Rs); + void jalr(Register Rs); + void ret(); + void call(const address &dest, Register temp = t0); + void call(const Address &adr, Register temp = t0); + void tail(const address &dest, Register temp = t0); + void tail(const Address &adr, Register temp = t0); + void call(Label &l, Register temp) { + call(target(l), temp); + } + void tail(Label &l, Register temp) { + tail(target(l), temp); + } + + static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) { + assert_cond(msb >= lsb && msb <= 31); + unsigned nbits = msb - lsb + 1; + uint32_t mask = (1U << nbits) - 1; + uint32_t result = val >> lsb; + result &= mask; + return result; + } + + static inline int32_t sextract(uint32_t val, unsigned msb, unsigned lsb) { + assert_cond(msb >= lsb && msb <= 31); + int32_t result = val << (31 - msb); + result >>= (31 - msb + lsb); + return result; + } + + static void patch(address a, unsigned msb, unsigned lsb, unsigned val) { + assert_cond(a != NULL); + assert_cond(msb >= lsb && msb <= 31); + unsigned nbits = msb - lsb + 1; + guarantee(val < (1U << nbits), "Field too big for insn"); + unsigned mask = (1U << nbits) - 1; + val <<= lsb; + mask <<= lsb; + unsigned target = *(unsigned *)a; + target &= ~mask; + target |= val; + *(unsigned *)a = target; + } + + static void patch(address a, unsigned bit, unsigned val) { + patch(a, bit, bit, val); + } + + static void patch_reg(address a, unsigned lsb, Register reg) { + patch(a, lsb + 4, lsb, reg->encoding_nocheck()); + } + + static void patch_reg(address a, unsigned lsb, FloatRegister reg) { + patch(a, lsb + 4, lsb, reg->encoding_nocheck()); + } + + static void patch_reg(address a, unsigned lsb, VectorRegister reg) { + patch(a, lsb + 4, lsb, reg->encoding_nocheck()); + } + + void emit(unsigned insn) { + emit_int32((jint)insn); + } + + void _halt() { + emit_int32(0); + } + +// Register Instruction +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + INSN(_add, 0b0110011, 0b000, 0b0000000); + INSN(_sub, 0b0110011, 0b000, 0b0100000); + INSN(_andr, 0b0110011, 0b111, 0b0000000); + INSN(_orr, 0b0110011, 0b110, 0b0000000); + INSN(_xorr, 0b0110011, 0b100, 0b0000000); + INSN(sll, 0b0110011, 0b001, 0b0000000); + INSN(sra, 0b0110011, 0b101, 0b0100000); + INSN(srl, 0b0110011, 0b101, 0b0000000); + INSN(slt, 0b0110011, 0b010, 0b0000000); + INSN(sltu, 0b0110011, 0b011, 0b0000000); + INSN(_addw, 0b0111011, 0b000, 0b0000000); + INSN(_subw, 0b0111011, 0b000, 0b0100000); + INSN(sllw, 0b0111011, 0b001, 0b0000000); + INSN(sraw, 0b0111011, 0b101, 0b0100000); + INSN(srlw, 0b0111011, 0b101, 0b0000000); + INSN(mul, 0b0110011, 0b000, 0b0000001); + INSN(mulh, 0b0110011, 0b001, 0b0000001); + INSN(mulhsu,0b0110011, 0b010, 0b0000001); + INSN(mulhu, 0b0110011, 0b011, 0b0000001); + INSN(mulw, 0b0111011, 0b000, 0b0000001); + INSN(div, 0b0110011, 0b100, 0b0000001); + INSN(divu, 0b0110011, 0b101, 0b0000001); + INSN(divw, 0b0111011, 0b100, 0b0000001); + INSN(divuw, 0b0111011, 0b101, 0b0000001); + INSN(rem, 0b0110011, 0b110, 0b0000001); + INSN(remu, 0b0110011, 0b111, 0b0000001); + INSN(remw, 0b0111011, 0b110, 0b0000001); + INSN(remuw, 0b0111011, 0b111, 0b0000001); + +#undef INSN + +#define INSN_ENTRY_RELOC(result_type, header) \ + result_type header { \ + InstructionMark im(this); \ + guarantee(rtype == relocInfo::internal_word_type, \ + "only internal_word_type relocs make sense here"); \ + code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); + + // Load/store register (all modes) +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ + unsigned insn = 0; \ + int32_t val = offset & 0xfff; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 15, Rs); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 31, 20, val); \ + emit(insn); \ + } + + INSN(lb, 0b0000011, 0b000); + INSN(lbu, 0b0000011, 0b100); + INSN(lh, 0b0000011, 0b001); + INSN(lhu, 0b0000011, 0b101); + INSN(_lw, 0b0000011, 0b010); + INSN(lwu, 0b0000011, 0b110); + INSN(_ld, 0b0000011, 0b011); + +#undef INSN + +#define INSN(NAME) \ + void NAME(Register Rd, address dest) { \ + assert_cond(dest != NULL); \ + int64_t distance = (dest - pc()); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(Rd, (int32_t)distance + 0x800); \ + NAME(Rd, Rd, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr_with_offset(Rd, dest, offset); \ + NAME(Rd, Rd, offset); \ + } \ + } \ + INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype)) \ + NAME(Rd, dest); \ + } \ + void NAME(Register Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + code_section()->relocate(pc(), adr.rspec()); \ + NAME(Rd, adr.target()); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + NAME(Rd, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + if (Rd == adr.base()) { \ + baseOffset32(temp, adr, offset); \ + NAME(Rd, temp, offset); \ + } else { \ + baseOffset32(Rd, adr, offset); \ + NAME(Rd, Rd, offset); \ + } \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } \ + void NAME(Register Rd, Label &L) { \ + wrap_label(Rd, L, &Assembler::NAME); \ + } + + INSN(lb); + INSN(lbu); + INSN(lh); + INSN(lhu); + INSN(lw); + INSN(lwu); + INSN(ld); + +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \ + guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ + unsigned insn = 0; \ + uint32_t val = offset & 0xfff; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 15, Rs); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 31, 20, val); \ + emit(insn); \ + } + + INSN(flw, 0b0000111, 0b010); + INSN(_fld, 0b0000111, 0b011); + +#undef INSN + +#define INSN(NAME) \ + void NAME(FloatRegister Rd, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + int64_t distance = (dest - pc()); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + NAME(Rd, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr_with_offset(temp, dest, offset); \ + NAME(Rd, temp, offset); \ + } \ + } \ + INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, relocInfo::relocType rtype, Register temp = t0)) \ + NAME(Rd, dest, temp); \ + } \ + void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + code_section()->relocate(pc(), adr.rspec()); \ + NAME(Rd, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + NAME(Rd, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + baseOffset32(temp, adr, offset); \ + NAME(Rd, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(flw); + INSN(fld); +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rs1, Register Rs2, const int64_t offset) { \ + guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \ + unsigned insn = 0; \ + uint32_t val = offset & 0x1fff; \ + uint32_t val11 = (val >> 11) & 0x1; \ + uint32_t val12 = (val >> 12) & 0x1; \ + uint32_t low = (val >> 1) & 0xf; \ + uint32_t high = (val >> 5) & 0x3f; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + patch((address)&insn, 7, val11); \ + patch((address)&insn, 11, 8, low); \ + patch((address)&insn, 30, 25, high); \ + patch((address)&insn, 31, val12); \ + emit(insn); \ + } + + INSN(_beq, 0b1100011, 0b000); + INSN(_bne, 0b1100011, 0b001); + INSN(bge, 0b1100011, 0b101); + INSN(bgeu, 0b1100011, 0b111); + INSN(blt, 0b1100011, 0b100); + INSN(bltu, 0b1100011, 0b110); + +#undef INSN + +#define INSN(NAME) \ + void NAME(Register Rs1, Register Rs2, const address dest) { \ + assert_cond(dest != NULL); \ + int64_t offset = (dest - pc()); \ + guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \ + NAME(Rs1, Rs2, offset); \ + } \ + INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype)) \ + NAME(Rs1, Rs2, dest); \ + } + + INSN(beq); + INSN(bne); + INSN(bge); + INSN(bgeu); + INSN(blt); + INSN(bltu); + +#undef INSN + +#define INSN(NAME, NEG_INSN) \ + void NAME(Register Rs1, Register Rs2, Label &L, bool is_far = false) { \ + wrap_label(Rs1, Rs2, L, &Assembler::NAME, &Assembler::NEG_INSN, is_far); \ + } + + INSN(beq, bne); + INSN(bne, beq); + INSN(blt, bge); + INSN(bge, blt); + INSN(bltu, bgeu); + INSN(bgeu, bltu); + +#undef INSN + +#define INSN(NAME, REGISTER, op, funct3) \ + void NAME(REGISTER Rs1, Register Rs2, const int32_t offset) { \ + guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ + unsigned insn = 0; \ + uint32_t val = offset & 0xfff; \ + uint32_t low = val & 0x1f; \ + uint32_t high = (val >> 5) & 0x7f; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 15, Rs2); \ + patch_reg((address)&insn, 20, Rs1); \ + patch((address)&insn, 11, 7, low); \ + patch((address)&insn, 31, 25, high); \ + emit(insn); \ + } \ + + INSN(sb, Register, 0b0100011, 0b000); + INSN(sh, Register, 0b0100011, 0b001); + INSN(_sw, Register, 0b0100011, 0b010); + INSN(_sd, Register, 0b0100011, 0b011); + INSN(fsw, FloatRegister, 0b0100111, 0b010); + INSN(_fsd, FloatRegister, 0b0100111, 0b011); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, relocInfo::relocType rtype, Register temp = t0)) \ + NAME(Rs, dest, temp); \ + } + + INSN(sb, Register); + INSN(sh, Register); + INSN(sw, Register); + INSN(sd, Register); + INSN(fsw, FloatRegister); + INSN(fsd, FloatRegister); + +#undef INSN + +#define INSN(NAME) \ + void NAME(Register Rs, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + assert_different_registers(Rs, temp); \ + int64_t distance = (dest - pc()); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr_with_offset(temp, dest, offset); \ + NAME(Rs, temp, offset); \ + } \ + } \ + void NAME(Register Rs, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + assert_different_registers(Rs, temp); \ + code_section()->relocate(pc(), adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + NAME(Rs, adr.base(), adr.offset()); \ + } else { \ + int32_t offset= 0; \ + assert_different_registers(Rs, temp); \ + baseOffset32(temp, adr, offset); \ + NAME(Rs, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(sb); + INSN(sh); + INSN(sw); + INSN(sd); + +#undef INSN + +#define INSN(NAME) \ + void NAME(FloatRegister Rs, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + int64_t distance = (dest - pc()); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr_with_offset(temp, dest, offset); \ + NAME(Rs, temp, offset); \ + } \ + } \ + void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + code_section()->relocate(pc(), adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + NAME(Rs, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + baseOffset32(temp, adr, offset); \ + NAME(Rs, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(fsw); + INSN(fsd); + +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, const uint32_t csr, Register Rs1) { \ + guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch((address)&insn, 31, 20, csr); \ + emit(insn); \ + } + + INSN(csrrw, 0b1110011, 0b001); + INSN(csrrs, 0b1110011, 0b010); + INSN(csrrc, 0b1110011, 0b011); + +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, const uint32_t csr, const uint32_t uimm) { \ + guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid"); \ + guarantee(is_unsigned_imm_in_range(uimm, 5, 0), "uimm is invalid"); \ + unsigned insn = 0; \ + uint32_t val = uimm & 0x1f; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 19, 15, val); \ + patch((address)&insn, 31, 20, csr); \ + emit(insn); \ + } + + INSN(csrrwi, 0b1110011, 0b101); + INSN(csrrsi, 0b1110011, 0b110); + INSN(csrrci, 0b1110011, 0b111); + +#undef INSN + +#define INSN(NAME, op) \ + void NAME(Register Rd, const int32_t offset) { \ + guarantee(is_imm_in_range(offset, 20, 1), "offset is invalid."); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff)); \ + patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1)); \ + patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff)); \ + patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1)); \ + emit(insn); \ + } + + INSN(_jal, 0b1101111); + +#undef INSN + +#define INSN(NAME) \ + void NAME(Register Rd, const address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + int64_t offset = dest - pc(); \ + if (is_imm_in_range(offset, 20, 1)) { \ + NAME(Rd, offset); \ + } else { \ + assert_different_registers(Rd, temp); \ + int32_t off = 0; \ + movptr_with_offset(temp, dest, off); \ + jalr(Rd, temp, off); \ + } \ + } \ + void NAME(Register Rd, Label &L, Register temp = t0) { \ + assert_different_registers(Rd, temp); \ + wrap_label(Rd, L, temp, &Assembler::NAME); \ + } + + INSN(jal); + +#undef INSN + +#undef INSN_ENTRY_RELOC + +#define INSN(NAME, op, funct) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 14, 12, funct); \ + patch_reg((address)&insn, 15, Rs); \ + int32_t val = offset & 0xfff; \ + patch((address)&insn, 31, 20, val); \ + emit(insn); \ + } + + INSN(_jalr, 0b1100111, 0b000); + +#undef INSN + + enum barrier { + i = 0b1000, o = 0b0100, r = 0b0010, w = 0b0001, + ir = i | r, ow = o | w, iorw = i | o | r | w + }; + + void fence(const uint32_t predecessor, const uint32_t successor) { + unsigned insn = 0; + guarantee(predecessor < 16, "predecessor is invalid"); + guarantee(successor < 16, "successor is invalid"); + patch((address)&insn, 6, 0, 0b001111); + patch((address)&insn, 11, 7, 0b00000); + patch((address)&insn, 14, 12, 0b000); + patch((address)&insn, 19, 15, 0b00000); + patch((address)&insn, 23, 20, successor); + patch((address)&insn, 27, 24, predecessor); + patch((address)&insn, 31, 28, 0b0000); + emit(insn); + } + +#define INSN(NAME, op, funct3, funct7) \ + void NAME() { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 11, 7, 0b00000); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 19, 15, 0b00000); \ + patch((address)&insn, 31, 20, funct7); \ + emit(insn); \ + } + + INSN(fence_i, 0b0001111, 0b001, 0b000000000000); + INSN(ecall, 0b1110011, 0b000, 0b000000000000); + INSN(_ebreak, 0b1110011, 0b000, 0b000000000001); + +#undef INSN + +enum Aqrl {relaxed = 0b00, rl = 0b01, aq = 0b10, aqrl = 0b11}; + +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2, Aqrl memory_order = aqrl) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + patch((address)&insn, 31, 27, funct7); \ + patch((address)&insn, 26, 25, memory_order); \ + emit(insn); \ + } + + INSN(amoswap_w, 0b0101111, 0b010, 0b00001); + INSN(amoadd_w, 0b0101111, 0b010, 0b00000); + INSN(amoxor_w, 0b0101111, 0b010, 0b00100); + INSN(amoand_w, 0b0101111, 0b010, 0b01100); + INSN(amoor_w, 0b0101111, 0b010, 0b01000); + INSN(amomin_w, 0b0101111, 0b010, 0b10000); + INSN(amomax_w, 0b0101111, 0b010, 0b10100); + INSN(amominu_w, 0b0101111, 0b010, 0b11000); + INSN(amomaxu_w, 0b0101111, 0b010, 0b11100); + INSN(amoswap_d, 0b0101111, 0b011, 0b00001); + INSN(amoadd_d, 0b0101111, 0b011, 0b00000); + INSN(amoxor_d, 0b0101111, 0b011, 0b00100); + INSN(amoand_d, 0b0101111, 0b011, 0b01100); + INSN(amoor_d, 0b0101111, 0b011, 0b01000); + INSN(amomin_d, 0b0101111, 0b011, 0b10000); + INSN(amomax_d , 0b0101111, 0b011, 0b10100); + INSN(amominu_d, 0b0101111, 0b011, 0b11000); + INSN(amomaxu_d, 0b0101111, 0b011, 0b11100); +#undef INSN + +enum operand_size { int8, int16, int32, uint32, int64 }; + +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Aqrl memory_order = relaxed) { \ + unsigned insn = 0; \ + uint32_t val = memory_order & 0x3; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch((address)&insn, 25, 20, 0b00000); \ + patch((address)&insn, 31, 27, funct7); \ + patch((address)&insn, 26, 25, val); \ + emit(insn); \ + } + + INSN(lr_w, 0b0101111, 0b010, 0b00010); + INSN(lr_d, 0b0101111, 0b011, 0b00010); + +#undef INSN + +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2, Aqrl memory_order = relaxed) { \ + unsigned insn = 0; \ + uint32_t val = memory_order & 0x3; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs2); \ + patch_reg((address)&insn, 20, Rs1); \ + patch((address)&insn, 31, 27, funct7); \ + patch((address)&insn, 26, 25, val); \ + emit(insn); \ + } + + INSN(sc_w, 0b0101111, 0b010, 0b00011); + INSN(sc_d, 0b0101111, 0b011, 0b00011); +#undef INSN + +#define INSN(NAME, op, funct5, funct7) \ + void NAME(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, rm); \ + patch((address)&insn, 24, 20, funct5); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(fsqrt_s, 0b1010011, 0b00000, 0b0101100); + INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101); + INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000); + INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001); +#undef INSN + +// Immediate Instruction +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, Register Rs1, int32_t imm) { \ + guarantee(is_imm_in_range(imm, 12, 0), "Immediate is out of validity"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 20, imm & 0x00000fff); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(_addi, 0b0010011, 0b000); + INSN(slti, 0b0010011, 0b010); + INSN(_addiw, 0b0011011, 0b000); + INSN(_and_imm12, 0b0010011, 0b111); + INSN(ori, 0b0010011, 0b110); + INSN(xori, 0b0010011, 0b100); + +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, Register Rs1, uint32_t imm) { \ + guarantee(is_unsigned_imm_in_range(imm, 12, 0), "Immediate is out of validity"); \ + unsigned insn = 0; \ + patch((address)&insn,6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 20, imm & 0x00000fff); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(sltiu, 0b0010011, 0b011); + +#undef INSN + +// Shift Immediate Instruction +#define INSN(NAME, op, funct3, funct6) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) { \ + guarantee(shamt <= 0x3f, "Shamt is invalid"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 25, 20, shamt); \ + patch((address)&insn, 31, 26, funct6); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(_slli, 0b0010011, 0b001, 0b000000); + INSN(_srai, 0b0010011, 0b101, 0b010000); + INSN(_srli, 0b0010011, 0b101, 0b000000); + +#undef INSN + +// Shift Word Immediate Instruction +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) { \ + guarantee(shamt <= 0x1f, "Shamt is invalid"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 24, 20, shamt); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(slliw, 0b0011011, 0b001, 0b0000000); + INSN(sraiw, 0b0011011, 0b101, 0b0100000); + INSN(srliw, 0b0011011, 0b101, 0b0000000); + +#undef INSN + +// Upper Immediate Instruction +#define INSN(NAME, op) \ + void NAME(Register Rd, int32_t imm) { \ + int32_t upperImm = imm >> 12; \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch_reg((address)&insn, 7, Rd); \ + upperImm &= 0x000fffff; \ + patch((address)&insn, 31, 12, upperImm); \ + emit(insn); \ + } + + INSN(_lui, 0b0110111); + INSN(auipc, 0b0010111); + +#undef INSN + +// Float and Double Rigster Instruction +#define INSN(NAME, op, funct2) \ + void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, rm); \ + patch((address)&insn, 26, 25, funct2); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + patch_reg((address)&insn, 27, Rs3); \ + emit(insn); \ + } + + INSN(fmadd_s, 0b1000011, 0b00); + INSN(fmsub_s, 0b1000111, 0b00); + INSN(fnmsub_s, 0b1001011, 0b00); + INSN(fnmadd_s, 0b1001111, 0b00); + INSN(fmadd_d, 0b1000011, 0b01); + INSN(fmsub_d, 0b1000111, 0b01); + INSN(fnmsub_d, 0b1001011, 0b01); + INSN(fnmadd_d, 0b1001111, 0b01); + +#undef INSN + +// Float and Double Rigster Instruction +#define INSN(NAME, op, funct3, funct7) \ + void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + INSN(fsgnj_s, 0b1010011, 0b000, 0b0010000); + INSN(fsgnjn_s, 0b1010011, 0b001, 0b0010000); + INSN(fsgnjx_s, 0b1010011, 0b010, 0b0010000); + INSN(fmin_s, 0b1010011, 0b000, 0b0010100); + INSN(fmax_s, 0b1010011, 0b001, 0b0010100); + INSN(fsgnj_d, 0b1010011, 0b000, 0b0010001); + INSN(fsgnjn_d, 0b1010011, 0b001, 0b0010001); + INSN(fsgnjx_d, 0b1010011, 0b010, 0b0010001); + INSN(fmin_d, 0b1010011, 0b000, 0b0010101); + INSN(fmax_d, 0b1010011, 0b001, 0b0010101); + +#undef INSN + +// Float and Double Rigster Arith Instruction +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + INSN(feq_s, 0b1010011, 0b010, 0b1010000); + INSN(flt_s, 0b1010011, 0b001, 0b1010000); + INSN(fle_s, 0b1010011, 0b000, 0b1010000); + INSN(feq_d, 0b1010011, 0b010, 0b1010001); + INSN(fle_d, 0b1010011, 0b000, 0b1010001); + INSN(flt_d, 0b1010011, 0b001, 0b1010001); +#undef INSN + +// Float and Double Arith Instruction +#define INSN(NAME, op, funct7) \ + void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, rm); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + INSN(fadd_s, 0b1010011, 0b0000000); + INSN(fsub_s, 0b1010011, 0b0000100); + INSN(fmul_s, 0b1010011, 0b0001000); + INSN(fdiv_s, 0b1010011, 0b0001100); + INSN(fadd_d, 0b1010011, 0b0000001); + INSN(fsub_d, 0b1010011, 0b0000101); + INSN(fmul_d, 0b1010011, 0b0001001); + INSN(fdiv_d, 0b1010011, 0b0001101); + +#undef INSN + +// Whole Float and Double Conversion Instruction +#define INSN(NAME, op, funct5, funct7) \ + void NAME(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, rm); \ + patch((address)&insn, 24, 20, funct5); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(fcvt_s_w, 0b1010011, 0b00000, 0b1101000); + INSN(fcvt_s_wu, 0b1010011, 0b00001, 0b1101000); + INSN(fcvt_s_l, 0b1010011, 0b00010, 0b1101000); + INSN(fcvt_s_lu, 0b1010011, 0b00011, 0b1101000); + INSN(fcvt_d_w, 0b1010011, 0b00000, 0b1101001); + INSN(fcvt_d_wu, 0b1010011, 0b00001, 0b1101001); + INSN(fcvt_d_l, 0b1010011, 0b00010, 0b1101001); + INSN(fcvt_d_lu, 0b1010011, 0b00011, 0b1101001); + +#undef INSN + +// Float and Double Conversion Instruction +#define INSN(NAME, op, funct5, funct7) \ + void NAME(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, rm); \ + patch((address)&insn, 24, 20, funct5); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(fcvt_w_s, 0b1010011, 0b00000, 0b1100000); + INSN(fcvt_l_s, 0b1010011, 0b00010, 0b1100000); + INSN(fcvt_wu_s, 0b1010011, 0b00001, 0b1100000); + INSN(fcvt_lu_s, 0b1010011, 0b00011, 0b1100000); + INSN(fcvt_w_d, 0b1010011, 0b00000, 0b1100001); + INSN(fcvt_wu_d, 0b1010011, 0b00001, 0b1100001); + INSN(fcvt_l_d, 0b1010011, 0b00010, 0b1100001); + INSN(fcvt_lu_d, 0b1010011, 0b00011, 0b1100001); + +#undef INSN + +// Float and Double Move Instruction +#define INSN(NAME, op, funct3, funct5, funct7) \ + void NAME(FloatRegister Rd, Register Rs1) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 20, funct5); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(fmv_w_x, 0b1010011, 0b000, 0b00000, 0b1111000); + INSN(fmv_d_x, 0b1010011, 0b000, 0b00000, 0b1111001); + +#undef INSN + +// Float and Double Conversion Instruction +#define INSN(NAME, op, funct3, funct5, funct7) \ + void NAME(Register Rd, FloatRegister Rs1) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 20, funct5); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(fclass_s, 0b1010011, 0b001, 0b00000, 0b1110000); + INSN(fclass_d, 0b1010011, 0b001, 0b00000, 0b1110001); + INSN(fmv_x_w, 0b1010011, 0b000, 0b00000, 0b1110000); + INSN(fmv_x_d, 0b1010011, 0b000, 0b00000, 0b1110001); + +#undef INSN + +// ========================== +// RISC-V Vector Extension +// ========================== +enum SEW { + e8, + e16, + e32, + e64, + RESERVED, +}; + +enum LMUL { + mf8 = 0b101, + mf4 = 0b110, + mf2 = 0b111, + m1 = 0b000, + m2 = 0b001, + m4 = 0b010, + m8 = 0b011, +}; + +enum VMA { + mu, // undisturbed + ma, // agnostic +}; + +enum VTA { + tu, // undisturbed + ta, // agnostic +}; + +static Assembler::SEW elembytes_to_sew(int ebytes) { + assert(ebytes > 0 && ebytes <= 8, "unsupported element size"); + return (Assembler::SEW) exact_log2(ebytes); +} + +static Assembler::SEW elemtype_to_sew(BasicType etype) { + return Assembler::elembytes_to_sew(type2aelembytes(etype)); +} + +#define patch_vtype(hsb, lsb, vlmul, vsew, vta, vma, vill) \ + if (vill == 1) { \ + guarantee((vlmul | vsew | vta | vma == 0), \ + "the other bits in vtype shall be zero"); \ + } \ + patch((address)&insn, lsb + 2, lsb, vlmul); \ + patch((address)&insn, lsb + 5, lsb + 3, vsew); \ + patch((address)&insn, lsb + 6, vta); \ + patch((address)&insn, lsb + 7, vma); \ + patch((address)&insn, hsb - 1, lsb + 8, 0); \ + patch((address)&insn, hsb, vill) + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, Register Rs1, SEW sew, LMUL lmul = m1, \ + VMA vma = mu, VTA vta = tu, bool vill = false) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch_vtype(30, 20, lmul, sew, vta, vma, vill); \ + patch((address)&insn, 31, 0); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(vsetvli, 0b1010111, 0b111); + +#undef INSN + +#define INSN(NAME, op, funct3) \ + void NAME(Register Rd, uint32_t imm, SEW sew, LMUL lmul = m1, \ + VMA vma = mu, VTA vta = tu, bool vill = false) { \ + unsigned insn = 0; \ + guarantee(is_unsigned_imm_in_range(imm, 5, 0), "imm is invalid"); \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 19, 15, imm); \ + patch_vtype(29, 20, lmul, sew, vta, vma, vill); \ + patch((address)&insn, 31, 30, 0b11); \ + patch_reg((address)&insn, 7, Rd); \ + emit(insn); \ + } + + INSN(vsetivli, 0b1010111, 0b111); + +#undef INSN + +#undef patch_vtype + +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + // Vector Configuration Instruction + INSN(vsetvl, 0b1010111, 0b111, 0b1000000); + +#undef INSN + +enum VectorMask { + v0_t = 0b0, + unmasked = 0b1 +}; + +#define patch_VArith(op, Reg, funct3, Reg_or_Imm5, Vs2, vm, funct6) \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 19, 15, Reg_or_Imm5); \ + patch((address)&insn, 25, vm); \ + patch((address)&insn, 31, 26, funct6); \ + patch_reg((address)&insn, 7, Reg); \ + patch_reg((address)&insn, 20, Vs2); \ + emit(insn) + +// r2_vm +#define INSN(NAME, op, funct3, Vs1, funct6) \ + void NAME(Register Rd, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Mask + INSN(vpopc_m, 0b1010111, 0b010, 0b10000, 0b010000); + INSN(vfirst_m, 0b1010111, 0b010, 0b10001, 0b010000); +#undef INSN + +#define INSN(NAME, op, funct3, Vs1, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Integer Extension + INSN(vzext_vf2, 0b1010111, 0b010, 0b00110, 0b010010); + INSN(vzext_vf4, 0b1010111, 0b010, 0b00100, 0b010010); + INSN(vzext_vf8, 0b1010111, 0b010, 0b00010, 0b010010); + INSN(vsext_vf2, 0b1010111, 0b010, 0b00111, 0b010010); + INSN(vsext_vf4, 0b1010111, 0b010, 0b00101, 0b010010); + INSN(vsext_vf8, 0b1010111, 0b010, 0b00011, 0b010010); + + // Vector Mask + INSN(vmsbf_m, 0b1010111, 0b010, 0b00001, 0b010100); + INSN(vmsif_m, 0b1010111, 0b010, 0b00011, 0b010100); + INSN(vmsof_m, 0b1010111, 0b010, 0b00010, 0b010100); + INSN(viota_m, 0b1010111, 0b010, 0b10000, 0b010100); + + // Vector Single-Width Floating-Point/Integer Type-Convert Instructions + INSN(vfcvt_xu_f_v, 0b1010111, 0b001, 0b00000, 0b010010); + INSN(vfcvt_x_f_v, 0b1010111, 0b001, 0b00001, 0b010010); + INSN(vfcvt_f_xu_v, 0b1010111, 0b001, 0b00010, 0b010010); + INSN(vfcvt_f_x_v, 0b1010111, 0b001, 0b00011, 0b010010); + INSN(vfcvt_rtz_xu_f_v, 0b1010111, 0b001, 0b00110, 0b010010); + INSN(vfcvt_rtz_x_f_v, 0b1010111, 0b001, 0b00111, 0b010010); + + // Vector Floating-Point Instruction + INSN(vfsqrt_v, 0b1010111, 0b001, 0b00000, 0b010011); + INSN(vfclass_v, 0b1010111, 0b001, 0b10000, 0b010011); + +#undef INSN + +// r2rd +#define INSN(NAME, op, funct3, simm5, vm, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2) { \ + patch_VArith(op, Vd, funct3, simm5, Vs2, vm, funct6); \ + } + + // Vector Whole Vector Register Move + INSN(vmv1r_v, 0b1010111, 0b011, 0b00000, 0b1, 0b100111); + INSN(vmv2r_v, 0b1010111, 0b011, 0b00001, 0b1, 0b100111); + INSN(vmv4r_v, 0b1010111, 0b011, 0b00011, 0b1, 0b100111); + INSN(vmv8r_v, 0b1010111, 0b011, 0b00111, 0b1, 0b100111); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs1, vm, funct6) \ + void NAME(FloatRegister Rd, VectorRegister Vs2) { \ + patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Floating-Point Move Instruction + INSN(vfmv_f_s, 0b1010111, 0b001, 0b00000, 0b1, 0b010000); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs1, vm, funct6) \ + void NAME(Register Rd, VectorRegister Vs2) { \ + patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Integer Scalar Move Instructions + INSN(vmv_x_s, 0b1010111, 0b010, 0b00000, 0b1, 0b010000); + +#undef INSN + +// r_vm +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, uint32_t imm, VectorMask vm = unmasked) { \ + guarantee(is_unsigned_imm_in_range(imm, 5, 0), "imm is invalid"); \ + patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6); \ + } + + // Vector Single-Width Bit Shift Instructions + INSN(vsra_vi, 0b1010111, 0b011, 0b101001); + INSN(vsrl_vi, 0b1010111, 0b011, 0b101000); + INSN(vsll_vi, 0b1010111, 0b011, 0b100101); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs1, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Single-Width Floating-Point Fused Multiply-Add Instructions + INSN(vfnmsub_vv, 0b1010111, 0b001, 0b101011); + INSN(vfmsub_vv, 0b1010111, 0b001, 0b101010); + INSN(vfnmadd_vv, 0b1010111, 0b001, 0b101001); + INSN(vfmadd_vv, 0b1010111, 0b001, 0b101000); + INSN(vfnmsac_vv, 0b1010111, 0b001, 0b101111); + INSN(vfmsac_vv, 0b1010111, 0b001, 0b101110); + INSN(vfmacc_vv, 0b1010111, 0b001, 0b101100); + INSN(vfnmacc_vv, 0b1010111, 0b001, 0b101101); + + // Vector Single-Width Integer Multiply-Add Instructions + INSN(vnmsub_vv, 0b1010111, 0b010, 0b101011); + INSN(vmadd_vv, 0b1010111, 0b010, 0b101001); + INSN(vnmsac_vv, 0b1010111, 0b010, 0b101111); + INSN(vmacc_vv, 0b1010111, 0b010, 0b101101); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Single-Width Integer Multiply-Add Instructions + INSN(vnmsub_vx, 0b1010111, 0b110, 0b101011); + INSN(vmadd_vx, 0b1010111, 0b110, 0b101001); + INSN(vnmsac_vx, 0b1010111, 0b110, 0b101111); + INSN(vmacc_vx, 0b1010111, 0b110, 0b101101); + + INSN(vrsub_vx, 0b1010111, 0b100, 0b000011); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, FloatRegister Rs1, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Single-Width Floating-Point Fused Multiply-Add Instructions + INSN(vfnmsub_vf, 0b1010111, 0b101, 0b101011); + INSN(vfmsub_vf, 0b1010111, 0b101, 0b101010); + INSN(vfnmadd_vf, 0b1010111, 0b101, 0b101001); + INSN(vfmadd_vf, 0b1010111, 0b101, 0b101000); + INSN(vfnmsac_vf, 0b1010111, 0b101, 0b101111); + INSN(vfmsac_vf, 0b1010111, 0b101, 0b101110); + INSN(vfmacc_vf, 0b1010111, 0b101, 0b101100); + INSN(vfnmacc_vf, 0b1010111, 0b101, 0b101101); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Single-Width Floating-Point Reduction Instructions + INSN(vfredsum_vs, 0b1010111, 0b001, 0b000001); + INSN(vfredosum_vs, 0b1010111, 0b001, 0b000011); + INSN(vfredmin_vs, 0b1010111, 0b001, 0b000101); + INSN(vfredmax_vs, 0b1010111, 0b001, 0b000111); + + // Vector Single-Width Integer Reduction Instructions + INSN(vredsum_vs, 0b1010111, 0b010, 0b000000); + INSN(vredand_vs, 0b1010111, 0b010, 0b000001); + INSN(vredor_vs, 0b1010111, 0b010, 0b000010); + INSN(vredxor_vs, 0b1010111, 0b010, 0b000011); + INSN(vredminu_vs, 0b1010111, 0b010, 0b000100); + INSN(vredmin_vs, 0b1010111, 0b010, 0b000101); + INSN(vredmaxu_vs, 0b1010111, 0b010, 0b000110); + INSN(vredmax_vs, 0b1010111, 0b010, 0b000111); + + // Vector Floating-Point Compare Instructions + INSN(vmfle_vv, 0b1010111, 0b001, 0b011001); + INSN(vmflt_vv, 0b1010111, 0b001, 0b011011); + INSN(vmfne_vv, 0b1010111, 0b001, 0b011100); + INSN(vmfeq_vv, 0b1010111, 0b001, 0b011000); + + // Vector Floating-Point Sign-Injection Instructions + INSN(vfsgnjx_vv, 0b1010111, 0b001, 0b001010); + INSN(vfsgnjn_vv, 0b1010111, 0b001, 0b001001); + INSN(vfsgnj_vv, 0b1010111, 0b001, 0b001000); + + // Vector Floating-Point MIN/MAX Instructions + INSN(vfmax_vv, 0b1010111, 0b001, 0b000110); + INSN(vfmin_vv, 0b1010111, 0b001, 0b000100); + + // Vector Single-Width Floating-Point Multiply/Divide Instructions + INSN(vfdiv_vv, 0b1010111, 0b001, 0b100000); + INSN(vfmul_vv, 0b1010111, 0b001, 0b100100); + + // Vector Single-Width Floating-Point Add/Subtract Instructions + INSN(vfsub_vv, 0b1010111, 0b001, 0b000010); + INSN(vfadd_vv, 0b1010111, 0b001, 0b000000); + + // Vector Single-Width Fractional Multiply with Rounding and Saturation + INSN(vsmul_vv, 0b1010111, 0b000, 0b100111); + + // Vector Integer Divide Instructions + INSN(vrem_vv, 0b1010111, 0b010, 0b100011); + INSN(vremu_vv, 0b1010111, 0b010, 0b100010); + INSN(vdiv_vv, 0b1010111, 0b010, 0b100001); + INSN(vdivu_vv, 0b1010111, 0b010, 0b100000); + + // Vector Single-Width Integer Multiply Instructions + INSN(vmulhsu_vv, 0b1010111, 0b010, 0b100110); + INSN(vmulhu_vv, 0b1010111, 0b010, 0b100100); + INSN(vmulh_vv, 0b1010111, 0b010, 0b100111); + INSN(vmul_vv, 0b1010111, 0b010, 0b100101); + + // Vector Integer Min/Max Instructions + INSN(vmax_vv, 0b1010111, 0b000, 0b000111); + INSN(vmaxu_vv, 0b1010111, 0b000, 0b000110); + INSN(vmin_vv, 0b1010111, 0b000, 0b000101); + INSN(vminu_vv, 0b1010111, 0b000, 0b000100); + + // Vector Integer Comparison Instructions + INSN(vmsle_vv, 0b1010111, 0b000, 0b011101); + INSN(vmsleu_vv, 0b1010111, 0b000, 0b011100); + INSN(vmslt_vv, 0b1010111, 0b000, 0b011011); + INSN(vmsltu_vv, 0b1010111, 0b000, 0b011010); + INSN(vmsne_vv, 0b1010111, 0b000, 0b011001); + INSN(vmseq_vv, 0b1010111, 0b000, 0b011000); + + // Vector Single-Width Bit Shift Instructions + INSN(vsra_vv, 0b1010111, 0b000, 0b101001); + INSN(vsrl_vv, 0b1010111, 0b000, 0b101000); + INSN(vsll_vv, 0b1010111, 0b000, 0b100101); + + // Vector Bitwise Logical Instructions + INSN(vxor_vv, 0b1010111, 0b000, 0b001011); + INSN(vor_vv, 0b1010111, 0b000, 0b001010); + INSN(vand_vv, 0b1010111, 0b000, 0b001001); + + // Vector Single-Width Integer Add and Subtract + INSN(vsub_vv, 0b1010111, 0b000, 0b000010); + INSN(vadd_vv, 0b1010111, 0b000, 0b000000); + +#undef INSN + + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, Register Rs1, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Integer Divide Instructions + INSN(vrem_vx, 0b1010111, 0b110, 0b100011); + INSN(vremu_vx, 0b1010111, 0b110, 0b100010); + INSN(vdiv_vx, 0b1010111, 0b110, 0b100001); + INSN(vdivu_vx, 0b1010111, 0b110, 0b100000); + + // Vector Single-Width Integer Multiply Instructions + INSN(vmulhsu_vx, 0b1010111, 0b110, 0b100110); + INSN(vmulhu_vx, 0b1010111, 0b110, 0b100100); + INSN(vmulh_vx, 0b1010111, 0b110, 0b100111); + INSN(vmul_vx, 0b1010111, 0b110, 0b100101); + + // Vector Integer Min/Max Instructions + INSN(vmax_vx, 0b1010111, 0b100, 0b000111); + INSN(vmaxu_vx, 0b1010111, 0b100, 0b000110); + INSN(vmin_vx, 0b1010111, 0b100, 0b000101); + INSN(vminu_vx, 0b1010111, 0b100, 0b000100); + + // Vector Integer Comparison Instructions + INSN(vmsgt_vx, 0b1010111, 0b100, 0b011111); + INSN(vmsgtu_vx, 0b1010111, 0b100, 0b011110); + INSN(vmsle_vx, 0b1010111, 0b100, 0b011101); + INSN(vmsleu_vx, 0b1010111, 0b100, 0b011100); + INSN(vmslt_vx, 0b1010111, 0b100, 0b011011); + INSN(vmsltu_vx, 0b1010111, 0b100, 0b011010); + INSN(vmsne_vx, 0b1010111, 0b100, 0b011001); + INSN(vmseq_vx, 0b1010111, 0b100, 0b011000); + + // Vector Narrowing Integer Right Shift Instructions + INSN(vnsra_wx, 0b1010111, 0b100, 0b101101); + INSN(vnsrl_wx, 0b1010111, 0b100, 0b101100); + + // Vector Single-Width Bit Shift Instructions + INSN(vsra_vx, 0b1010111, 0b100, 0b101001); + INSN(vsrl_vx, 0b1010111, 0b100, 0b101000); + INSN(vsll_vx, 0b1010111, 0b100, 0b100101); + + // Vector Bitwise Logical Instructions + INSN(vxor_vx, 0b1010111, 0b100, 0b001011); + INSN(vor_vx, 0b1010111, 0b100, 0b001010); + INSN(vand_vx, 0b1010111, 0b100, 0b001001); + + // Vector Single-Width Integer Add and Subtract + INSN(vsub_vx, 0b1010111, 0b100, 0b000010); + INSN(vadd_vx, 0b1010111, 0b100, 0b000000); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, FloatRegister Rs1, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Floating-Point Compare Instructions + INSN(vmfge_vf, 0b1010111, 0b101, 0b011111); + INSN(vmfgt_vf, 0b1010111, 0b101, 0b011101); + INSN(vmfle_vf, 0b1010111, 0b101, 0b011001); + INSN(vmflt_vf, 0b1010111, 0b101, 0b011011); + INSN(vmfne_vf, 0b1010111, 0b101, 0b011100); + INSN(vmfeq_vf, 0b1010111, 0b101, 0b011000); + + // Vector Floating-Point Sign-Injection Instructions + INSN(vfsgnjx_vf, 0b1010111, 0b101, 0b001010); + INSN(vfsgnjn_vf, 0b1010111, 0b101, 0b001001); + INSN(vfsgnj_vf, 0b1010111, 0b101, 0b001000); + + // Vector Floating-Point MIN/MAX Instructions + INSN(vfmax_vf, 0b1010111, 0b101, 0b000110); + INSN(vfmin_vf, 0b1010111, 0b101, 0b000100); + + // Vector Single-Width Floating-Point Multiply/Divide Instructions + INSN(vfdiv_vf, 0b1010111, 0b101, 0b100000); + INSN(vfmul_vf, 0b1010111, 0b101, 0b100100); + INSN(vfrdiv_vf, 0b1010111, 0b101, 0b100001); + + // Vector Single-Width Floating-Point Add/Subtract Instructions + INSN(vfsub_vf, 0b1010111, 0b101, 0b000010); + INSN(vfadd_vf, 0b1010111, 0b101, 0b000000); + INSN(vfrsub_vf, 0b1010111, 0b101, 0b100111); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, int32_t imm, VectorMask vm = unmasked) { \ + guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid"); \ + patch_VArith(op, Vd, funct3, (uint32_t)imm & 0x1f, Vs2, vm, funct6); \ + } + + INSN(vmsgt_vi, 0b1010111, 0b011, 0b011111); + INSN(vmsgtu_vi, 0b1010111, 0b011, 0b011110); + INSN(vmsle_vi, 0b1010111, 0b011, 0b011101); + INSN(vmsleu_vi, 0b1010111, 0b011, 0b011100); + INSN(vmsne_vi, 0b1010111, 0b011, 0b011001); + INSN(vmseq_vi, 0b1010111, 0b011, 0b011000); + INSN(vxor_vi, 0b1010111, 0b011, 0b001011); + INSN(vor_vi, 0b1010111, 0b011, 0b001010); + INSN(vand_vi, 0b1010111, 0b011, 0b001001); + INSN(vadd_vi, 0b1010111, 0b011, 0b000000); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, int32_t imm, VectorRegister Vs2, VectorMask vm = unmasked) { \ + guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid"); \ + patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6); \ + } + + INSN(vrsub_vi, 0b1010111, 0b011, 0b000011); + +#undef INSN + +#define INSN(NAME, op, funct3, vm, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1) { \ + patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Compress Instruction + INSN(vcompress_vm, 0b1010111, 0b010, 0b1, 0b010111); + + // Vector Mask-Register Logical Instructions + INSN(vmxnor_mm, 0b1010111, 0b010, 0b1, 0b011111); + INSN(vmornot_mm, 0b1010111, 0b010, 0b1, 0b011100); + INSN(vmnor_mm, 0b1010111, 0b010, 0b1, 0b011110); + INSN(vmor_mm, 0b1010111, 0b010, 0b1, 0b011010); + INSN(vmxor_mm, 0b1010111, 0b010, 0b1, 0b011011); + INSN(vmandnot_mm, 0b1010111, 0b010, 0b1, 0b011000); + INSN(vmnand_mm, 0b1010111, 0b010, 0b1, 0b011101); + INSN(vmand_mm, 0b1010111, 0b010, 0b1, 0b011001); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs2, vm, funct6) \ + void NAME(VectorRegister Vd, int32_t imm) { \ + guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid"); \ + patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6); \ + } + + // Vector Integer Move Instructions + INSN(vmv_v_i, 0b1010111, 0b011, v0, 0b1, 0b010111); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs2, vm, funct6) \ + void NAME(VectorRegister Vd, FloatRegister Rs1) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Floating-Point Scalar Move Instructions + INSN(vfmv_s_f, 0b1010111, 0b101, v0, 0b1, 0b010000); + // Vector Floating-Point Move Instruction + INSN(vfmv_v_f, 0b1010111, 0b101, v0, 0b1, 0b010111); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs2, vm, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs1) { \ + patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Vector Integer Move Instructions + INSN(vmv_v_v, 0b1010111, 0b000, v0, 0b1, 0b010111); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs2, vm, funct6) \ + void NAME(VectorRegister Vd, Register Rs1) { \ + patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \ + } + + // Integer Scalar Move Instructions + INSN(vmv_s_x, 0b1010111, 0b110, v0, 0b1, 0b010000); + + // Vector Integer Move Instructions + INSN(vmv_v_x, 0b1010111, 0b100, v0, 0b1, 0b010111); + +#undef INSN +#undef patch_VArith + +#define INSN(NAME, op, funct13, funct6) \ + void NAME(VectorRegister Vd, VectorMask vm = unmasked) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 24, 12, funct13); \ + patch((address)&insn, 25, vm); \ + patch((address)&insn, 31, 26, funct6); \ + patch_reg((address)&insn, 7, Vd); \ + emit(insn); \ + } + + // Vector Element Index Instruction + INSN(vid_v, 0b1010111, 0b0000010001010, 0b010100); + +#undef INSN + +enum Nf { + g1 = 0b000, + g2 = 0b001, + g3 = 0b010, + g4 = 0b011, + g5 = 0b100, + g6 = 0b101, + g7 = 0b110, + g8 = 0b111 +}; + +#define patch_VLdSt(op, VReg, width, Rs1, Reg_or_umop, vm, mop, mew, nf) \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, width); \ + patch((address)&insn, 24, 20, Reg_or_umop); \ + patch((address)&insn, 25, vm); \ + patch((address)&insn, 27, 26, mop); \ + patch((address)&insn, 28, mew); \ + patch((address)&insn, 31, 29, nf); \ + patch_reg((address)&insn, 7, VReg); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn) + +#define INSN(NAME, op, lumop, vm, mop, nf) \ + void NAME(VectorRegister Vd, Register Rs1, uint32_t width = 0, bool mew = false) { \ + guarantee(is_unsigned_imm_in_range(width, 3, 0), "width is invalid"); \ + patch_VLdSt(op, Vd, width, Rs1, lumop, vm, mop, mew, nf); \ + } + + // Vector Load/Store Instructions + INSN(vl1r_v, 0b0000111, 0b01000, 0b1, 0b00, g1); + +#undef INSN + +#define INSN(NAME, op, width, sumop, vm, mop, mew, nf) \ + void NAME(VectorRegister Vs3, Register Rs1) { \ + patch_VLdSt(op, Vs3, width, Rs1, sumop, vm, mop, mew, nf); \ + } + + // Vector Load/Store Instructions + INSN(vs1r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g1); + +#undef INSN + +// r2_nfvm +#define INSN(NAME, op, width, umop, mop, mew) \ + void NAME(VectorRegister Vd_or_Vs3, Register Rs1, Nf nf = g1) { \ + patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, 1, mop, mew, nf); \ + } + + // Vector Unit-Stride Instructions + INSN(vle1_v, 0b0000111, 0b000, 0b01011, 0b00, 0b0); + INSN(vse1_v, 0b0100111, 0b000, 0b01011, 0b00, 0b0); + +#undef INSN + +#define INSN(NAME, op, width, umop, mop, mew) \ + void NAME(VectorRegister Vd_or_Vs3, Register Rs1, VectorMask vm = unmasked, Nf nf = g1) { \ + patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, vm, mop, mew, nf); \ + } + + // Vector Unit-Stride Instructions + INSN(vle8_v, 0b0000111, 0b000, 0b00000, 0b00, 0b0); + INSN(vle16_v, 0b0000111, 0b101, 0b00000, 0b00, 0b0); + INSN(vle32_v, 0b0000111, 0b110, 0b00000, 0b00, 0b0); + INSN(vle64_v, 0b0000111, 0b111, 0b00000, 0b00, 0b0); + + // Vector unit-stride fault-only-first Instructions + INSN(vle8ff_v, 0b0000111, 0b000, 0b10000, 0b00, 0b0); + INSN(vle16ff_v, 0b0000111, 0b101, 0b10000, 0b00, 0b0); + INSN(vle32ff_v, 0b0000111, 0b110, 0b10000, 0b00, 0b0); + INSN(vle64ff_v, 0b0000111, 0b111, 0b10000, 0b00, 0b0); + + INSN(vse8_v, 0b0100111, 0b000, 0b00000, 0b00, 0b0); + INSN(vse16_v, 0b0100111, 0b101, 0b00000, 0b00, 0b0); + INSN(vse32_v, 0b0100111, 0b110, 0b00000, 0b00, 0b0); + INSN(vse64_v, 0b0100111, 0b111, 0b00000, 0b00, 0b0); + +#undef INSN + +#define INSN(NAME, op, width, mop, mew) \ + void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked, Nf nf = g1) { \ + patch_VLdSt(op, Vd, width, Rs1, Vs2->encoding_nocheck(), vm, mop, mew, nf); \ + } + + // Vector unordered indexed load instructions + INSN(vluxei8_v, 0b0000111, 0b000, 0b01, 0b0); + INSN(vluxei16_v, 0b0000111, 0b101, 0b01, 0b0); + INSN(vluxei32_v, 0b0000111, 0b110, 0b01, 0b0); + INSN(vluxei64_v, 0b0000111, 0b111, 0b01, 0b0); + + // Vector ordered indexed load instructions + INSN(vloxei8_v, 0b0000111, 0b000, 0b11, 0b0); + INSN(vloxei16_v, 0b0000111, 0b101, 0b11, 0b0); + INSN(vloxei32_v, 0b0000111, 0b110, 0b11, 0b0); + INSN(vloxei64_v, 0b0000111, 0b111, 0b11, 0b0); +#undef INSN + +#define INSN(NAME, op, width, mop, mew) \ + void NAME(VectorRegister Vd, Register Rs1, Register Rs2, VectorMask vm = unmasked, Nf nf = g1) { \ + patch_VLdSt(op, Vd, width, Rs1, Rs2->encoding_nocheck(), vm, mop, mew, nf); \ + } + + // Vector Strided Instructions + INSN(vlse8_v, 0b0000111, 0b000, 0b10, 0b0); + INSN(vlse16_v, 0b0000111, 0b101, 0b10, 0b0); + INSN(vlse32_v, 0b0000111, 0b110, 0b10, 0b0); + INSN(vlse64_v, 0b0000111, 0b111, 0b10, 0b0); + +#undef INSN +#undef patch_VLdSt + +// ==================================== +// RISC-V Bit-Manipulation Extension +// Currently only support Zba and Zbb. +// ==================================== +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + patch_reg((address)&insn, 20, Rs2); \ + emit(insn); \ + } + + INSN(add_uw, 0b0111011, 0b000, 0b0000100); + INSN(rol, 0b0110011, 0b001, 0b0110000); + INSN(rolw, 0b0111011, 0b001, 0b0110000); + INSN(ror, 0b0110011, 0b101, 0b0110000); + INSN(rorw, 0b0111011, 0b101, 0b0110000); + INSN(sh1add, 0b0110011, 0b010, 0b0010000); + INSN(sh2add, 0b0110011, 0b100, 0b0010000); + INSN(sh3add, 0b0110011, 0b110, 0b0010000); + INSN(sh1add_uw, 0b0111011, 0b010, 0b0010000); + INSN(sh2add_uw, 0b0111011, 0b100, 0b0010000); + INSN(sh3add_uw, 0b0111011, 0b110, 0b0010000); + INSN(andn, 0b0110011, 0b111, 0b0100000); + INSN(orn, 0b0110011, 0b110, 0b0100000); + INSN(xnor, 0b0110011, 0b100, 0b0100000); + INSN(max, 0b0110011, 0b110, 0b0000101); + INSN(maxu, 0b0110011, 0b111, 0b0000101); + INSN(min, 0b0110011, 0b100, 0b0000101); + INSN(minu, 0b0110011, 0b101, 0b0000101); + +#undef INSN + +#define INSN(NAME, op, funct3, funct12) \ + void NAME(Register Rd, Register Rs1) { \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 31, 20, funct12); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(rev8, 0b0010011, 0b101, 0b011010111000); + INSN(sext_b, 0b0010011, 0b001, 0b011000000100); + INSN(sext_h, 0b0010011, 0b001, 0b011000000101); + INSN(zext_h, 0b0111011, 0b100, 0b000010000000); + INSN(clz, 0b0010011, 0b001, 0b011000000000); + INSN(clzw, 0b0011011, 0b001, 0b011000000000); + INSN(ctz, 0b0010011, 0b001, 0b011000000001); + INSN(ctzw, 0b0011011, 0b001, 0b011000000001); + INSN(cpop, 0b0010011, 0b001, 0b011000000010); + INSN(cpopw, 0b0011011, 0b001, 0b011000000010); + INSN(orc_b, 0b0010011, 0b101, 0b001010000111); + +#undef INSN + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) {\ + guarantee(shamt <= 0x3f, "Shamt is invalid"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 25, 20, shamt); \ + patch((address)&insn, 31, 26, funct6); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(rori, 0b0010011, 0b101, 0b011000); + INSN(slli_uw, 0b0011011, 0b001, 0b000010); + +#undef INSN + +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) {\ + guarantee(shamt <= 0x1f, "Shamt is invalid"); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch((address)&insn, 14, 12, funct3); \ + patch((address)&insn, 24, 20, shamt); \ + patch((address)&insn, 31, 25, funct7); \ + patch_reg((address)&insn, 7, Rd); \ + patch_reg((address)&insn, 15, Rs1); \ + emit(insn); \ + } + + INSN(roriw, 0b0011011, 0b101, 0b0110000); + +#undef INSN + +// ======================================== +// RISC-V Compressed Instructions Extension +// ======================================== +// Note: +// 1. When UseRVC is enabled, 32-bit instructions under 'CompressibleRegion's will be +// transformed to 16-bit instructions if compressible. +// 2. RVC instructions in Assembler always begin with 'c_' prefix, as 'c_li', +// but most of time we have no need to explicitly use these instructions. +// 3. 'CompressibleRegion' is introduced to hint instructions in this Region's RTTI range +// are qualified to be compressed with their 2-byte versions. +// An example: +// +// CompressibleRegion cr(_masm); +// __ andr(...); // this instruction could change to c.and if able to +// +// 4. Using -XX:PrintAssemblyOptions=no-aliases could distinguish RVC instructions from +// normal ones. +// + +private: + bool _in_compressible_region; +public: + bool in_compressible_region() const { return _in_compressible_region; } + void set_in_compressible_region(bool b) { _in_compressible_region = b; } +public: + + // a compressible region + class CompressibleRegion : public StackObj { + protected: + Assembler *_masm; + bool _saved_in_compressible_region; + public: + CompressibleRegion(Assembler *_masm) + : _masm(_masm) + , _saved_in_compressible_region(_masm->in_compressible_region()) { + _masm->set_in_compressible_region(true); + } + ~CompressibleRegion() { + _masm->set_in_compressible_region(_saved_in_compressible_region); + } + }; + + // patch a 16-bit instruction. + static void c_patch(address a, unsigned msb, unsigned lsb, uint16_t val) { + assert_cond(a != NULL); + assert_cond(msb >= lsb && msb <= 15); + unsigned nbits = msb - lsb + 1; + guarantee(val < (1U << nbits), "Field too big for insn"); + uint16_t mask = (1U << nbits) - 1; + val <<= lsb; + mask <<= lsb; + uint16_t target = *(uint16_t *)a; + target &= ~mask; + target |= val; + *(uint16_t *)a = target; + } + + static void c_patch(address a, unsigned bit, uint16_t val) { + c_patch(a, bit, bit, val); + } + + // patch a 16-bit instruction with a general purpose register ranging [0, 31] (5 bits) + static void c_patch_reg(address a, unsigned lsb, Register reg) { + c_patch(a, lsb + 4, lsb, reg->encoding_nocheck()); + } + + // patch a 16-bit instruction with a general purpose register ranging [8, 15] (3 bits) + static void c_patch_compressed_reg(address a, unsigned lsb, Register reg) { + c_patch(a, lsb + 2, lsb, reg->compressed_encoding_nocheck()); + } + + // patch a 16-bit instruction with a float register ranging [0, 31] (5 bits) + static void c_patch_reg(address a, unsigned lsb, FloatRegister reg) { + c_patch(a, lsb + 4, lsb, reg->encoding_nocheck()); + } + + // patch a 16-bit instruction with a float register ranging [8, 15] (3 bits) + static void c_patch_compressed_reg(address a, unsigned lsb, FloatRegister reg) { + c_patch(a, lsb + 2, lsb, reg->compressed_encoding_nocheck()); + } + +// -------------- RVC Instruction Definitions -------------- + + void c_nop() { + c_addi(x0, 0); + } + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd_Rs1, int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 6, 0)); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (imm & right_n_bits(5))); \ + c_patch_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 12, 12, (imm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_addi, 0b000, 0b01); + INSN(c_addiw, 0b001, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 10, 0)); \ + assert_cond((imm & 0b1111) == 0); \ + assert_cond(imm != 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 2, 2, (imm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 4, 3, (imm & right_n_bits(9)) >> 7); \ + c_patch((address)&insn, 5, 5, (imm & nth_bit(6)) >> 6); \ + c_patch((address)&insn, 6, 6, (imm & nth_bit(4)) >> 4); \ + c_patch_reg((address)&insn, 7, sp); \ + c_patch((address)&insn, 12, 12, (imm & nth_bit(9)) >> 9); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_addi16sp, 0b011, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 10, 0)); \ + assert_cond((uimm & 0b11) == 0); \ + assert_cond(uimm != 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_compressed_reg((address)&insn, 2, Rd); \ + c_patch((address)&insn, 5, 5, (uimm & nth_bit(3)) >> 3); \ + c_patch((address)&insn, 6, 6, (uimm & nth_bit(2)) >> 2); \ + c_patch((address)&insn, 10, 7, (uimm & right_n_bits(10)) >> 6); \ + c_patch((address)&insn, 12, 11, (uimm & right_n_bits(6)) >> 4); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_addi4spn, 0b000, 0b00); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd_Rs1, uint32_t shamt) { \ + assert_cond(is_unsigned_imm_in_range(shamt, 6, 0)); \ + assert_cond(shamt != 0); \ + assert_cond(Rd_Rs1 != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (shamt & right_n_bits(5))); \ + c_patch_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 12, 12, (shamt & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_slli, 0b000, 0b10); + +#undef INSN + +#define INSN(NAME, funct3, funct2, op) \ + void NAME(Register Rd_Rs1, uint32_t shamt) { \ + assert_cond(is_unsigned_imm_in_range(shamt, 6, 0)); \ + assert_cond(shamt != 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (shamt & right_n_bits(5))); \ + c_patch_compressed_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 11, 10, funct2); \ + c_patch((address)&insn, 12, 12, (shamt & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_srli, 0b100, 0b00, 0b01); + INSN(c_srai, 0b100, 0b01, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, funct2, op) \ + void NAME(Register Rd_Rs1, int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 6, 0)); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (imm & right_n_bits(5))); \ + c_patch_compressed_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 11, 10, funct2); \ + c_patch((address)&insn, 12, 12, (imm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_andi, 0b100, 0b10, 0b01); + +#undef INSN + +#define INSN(NAME, funct6, funct2, op) \ + void NAME(Register Rd_Rs1, Register Rs2) { \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_compressed_reg((address)&insn, 2, Rs2); \ + c_patch((address)&insn, 6, 5, funct2); \ + c_patch_compressed_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 15, 10, funct6); \ + emit_int16(insn); \ + } + + INSN(c_sub, 0b100011, 0b00, 0b01); + INSN(c_xor, 0b100011, 0b01, 0b01); + INSN(c_or, 0b100011, 0b10, 0b01); + INSN(c_and, 0b100011, 0b11, 0b01); + INSN(c_subw, 0b100111, 0b00, 0b01); + INSN(c_addw, 0b100111, 0b01, 0b01); + +#undef INSN + +#define INSN(NAME, funct4, op) \ + void NAME(Register Rd_Rs1, Register Rs2) { \ + assert_cond(Rd_Rs1 != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_reg((address)&insn, 2, Rs2); \ + c_patch_reg((address)&insn, 7, Rd_Rs1); \ + c_patch((address)&insn, 15, 12, funct4); \ + emit_int16(insn); \ + } + + INSN(c_mv, 0b1000, 0b10); + INSN(c_add, 0b1001, 0b10); + +#undef INSN + +#define INSN(NAME, funct4, op) \ + void NAME(Register Rs1) { \ + assert_cond(Rs1 != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_reg((address)&insn, 2, x0); \ + c_patch_reg((address)&insn, 7, Rs1); \ + c_patch((address)&insn, 15, 12, funct4); \ + emit_int16(insn); \ + } + + INSN(c_jr, 0b1000, 0b10); + INSN(c_jalr, 0b1001, 0b10); + +#undef INSN + + typedef void (Assembler::* j_c_insn)(address dest); + typedef void (Assembler::* compare_and_branch_c_insn)(Register Rs1, address dest); + + void wrap_label(Label &L, j_c_insn insn) { + if (L.is_bound()) { + (this->*insn)(target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(pc()); + } + } + + void wrap_label(Label &L, Register r, compare_and_branch_c_insn insn) { + if (L.is_bound()) { + (this->*insn)(r, target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(r, pc()); + } + } + +#define INSN(NAME, funct3, op) \ + void NAME(int32_t offset) { \ + assert_cond(is_imm_in_range(offset, 11, 1)); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 2, 2, (offset & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 5, 3, (offset & right_n_bits(4)) >> 1); \ + c_patch((address)&insn, 6, 6, (offset & nth_bit(7)) >> 7); \ + c_patch((address)&insn, 7, 7, (offset & nth_bit(6)) >> 6); \ + c_patch((address)&insn, 8, 8, (offset & nth_bit(10)) >> 10); \ + c_patch((address)&insn, 10, 9, (offset & right_n_bits(10)) >> 8); \ + c_patch((address)&insn, 11, 11, (offset & nth_bit(4)) >> 4); \ + c_patch((address)&insn, 12, 12, (offset & nth_bit(11)) >> 11); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } \ + void NAME(address dest) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + assert_cond(is_imm_in_range(distance, 11, 1)); \ + c_j(distance); \ + } \ + void NAME(Label &L) { \ + wrap_label(L, &Assembler::NAME); \ + } + + INSN(c_j, 0b101, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rs1, int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 8, 1)); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 2, 2, (imm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 4, 3, (imm & right_n_bits(3)) >> 1); \ + c_patch((address)&insn, 6, 5, (imm & right_n_bits(8)) >> 6); \ + c_patch_compressed_reg((address)&insn, 7, Rs1); \ + c_patch((address)&insn, 11, 10, (imm & right_n_bits(5)) >> 3); \ + c_patch((address)&insn, 12, 12, (imm & nth_bit(8)) >> 8); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } \ + void NAME(Register Rs1, address dest) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + assert_cond(is_imm_in_range(distance, 8, 1)); \ + NAME(Rs1, distance); \ + } \ + void NAME(Register Rs1, Label &L) { \ + wrap_label(L, Rs1, &Assembler::NAME); \ + } + + INSN(c_beqz, 0b110, 0b01); + INSN(c_bnez, 0b111, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd, int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 18, 0)); \ + assert_cond((imm & 0xfff) == 0); \ + assert_cond(imm != 0); \ + assert_cond(Rd != x0 && Rd != x2); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (imm & right_n_bits(17)) >> 12); \ + c_patch_reg((address)&insn, 7, Rd); \ + c_patch((address)&insn, 12, 12, (imm & nth_bit(17)) >> 17); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_lui, 0b011, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd, int32_t imm) { \ + assert_cond(is_imm_in_range(imm, 6, 0)); \ + assert_cond(Rd != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 6, 2, (imm & right_n_bits(5))); \ + c_patch_reg((address)&insn, 7, Rd); \ + c_patch((address)&insn, 12, 12, (imm & right_n_bits(6)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_li, 0b010, 0b01); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 9, 0)); \ + assert_cond((uimm & 0b111) == 0); \ + assert_cond(Rd != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 4, 2, (uimm & right_n_bits(9)) >> 6); \ + c_patch((address)&insn, 6, 5, (uimm & right_n_bits(5)) >> 3); \ + c_patch_reg((address)&insn, 7, Rd); \ + c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_ldsp, 0b011, 0b10); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(FloatRegister Rd, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 9, 0)); \ + assert_cond((uimm & 0b111) == 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 4, 2, (uimm & right_n_bits(9)) >> 6); \ + c_patch((address)&insn, 6, 5, (uimm & right_n_bits(5)) >> 3); \ + c_patch_reg((address)&insn, 7, Rd); \ + c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_fldsp, 0b001, 0b10); + +#undef INSN + +#define INSN(NAME, funct3, op, REGISTER_TYPE) \ + void NAME(REGISTER_TYPE Rd_Rs2, Register Rs1, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 8, 0)); \ + assert_cond((uimm & 0b111) == 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); \ + c_patch((address)&insn, 6, 5, (uimm & right_n_bits(8)) >> 6); \ + c_patch_compressed_reg((address)&insn, 7, Rs1); \ + c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_ld, 0b011, 0b00, Register); + INSN(c_sd, 0b111, 0b00, Register); + INSN(c_fld, 0b001, 0b00, FloatRegister); + INSN(c_fsd, 0b101, 0b00, FloatRegister); + +#undef INSN + +#define INSN(NAME, funct3, op, REGISTER_TYPE) \ + void NAME(REGISTER_TYPE Rs2, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 9, 0)); \ + assert_cond((uimm & 0b111) == 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_reg((address)&insn, 2, Rs2); \ + c_patch((address)&insn, 9, 7, (uimm & right_n_bits(9)) >> 6); \ + c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_sdsp, 0b111, 0b10, Register); + INSN(c_fsdsp, 0b101, 0b10, FloatRegister); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rs2, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 8, 0)); \ + assert_cond((uimm & 0b11) == 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_reg((address)&insn, 2, Rs2); \ + c_patch((address)&insn, 8, 7, (uimm & right_n_bits(8)) >> 6); \ + c_patch((address)&insn, 12, 9, (uimm & right_n_bits(6)) >> 2); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_swsp, 0b110, 0b10); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 8, 0)); \ + assert_cond((uimm & 0b11) == 0); \ + assert_cond(Rd != x0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 3, 2, (uimm & right_n_bits(8)) >> 6); \ + c_patch((address)&insn, 6, 4, (uimm & right_n_bits(5)) >> 2); \ + c_patch_reg((address)&insn, 7, Rd); \ + c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_lwsp, 0b010, 0b10); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME(Register Rd_Rs2, Register Rs1, uint32_t uimm) { \ + assert_cond(is_unsigned_imm_in_range(uimm, 7, 0)); \ + assert_cond((uimm & 0b11) == 0); \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); \ + c_patch((address)&insn, 5, 5, (uimm & nth_bit(6)) >> 6); \ + c_patch((address)&insn, 6, 6, (uimm & nth_bit(2)) >> 2); \ + c_patch_compressed_reg((address)&insn, 7, Rs1); \ + c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_lw, 0b010, 0b00); + INSN(c_sw, 0b110, 0b00); + +#undef INSN + +#define INSN(NAME, funct3, op) \ + void NAME() { \ + uint16_t insn = 0; \ + c_patch((address)&insn, 1, 0, op); \ + c_patch((address)&insn, 11, 2, 0x0); \ + c_patch((address)&insn, 12, 12, 0b1); \ + c_patch((address)&insn, 15, 13, funct3); \ + emit_int16(insn); \ + } + + INSN(c_ebreak, 0b100, 0b10); + +#undef INSN + +// -------------- RVC Transformation Functions -------------- + +// -------------------------- +// Register instructions +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + /* add -> c.add */ \ + if (do_compress()) { \ + Register src = noreg; \ + if (Rs1 != x0 && Rs2 != x0 && ((src = Rs1, Rs2 == Rd) || (src = Rs2, Rs1 == Rd))) { \ + c_add(Rd, src); \ + return; \ + } \ + } \ + _add(Rd, Rs1, Rs2); \ + } + + INSN(add); + +#undef INSN + +// -------------------------- +#define INSN(NAME, C_NAME, NORMAL_NAME) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + /* sub/subw -> c.sub/c.subw */ \ + if (do_compress() && \ + (Rd == Rs1 && Rd->is_compressed_valid() && Rs2->is_compressed_valid())) { \ + C_NAME(Rd, Rs2); \ + return; \ + } \ + NORMAL_NAME(Rd, Rs1, Rs2); \ + } + + INSN(sub, c_sub, _sub); + INSN(subw, c_subw, _subw); + +#undef INSN + +// -------------------------- +#define INSN(NAME, C_NAME, NORMAL_NAME) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ + /* and/or/xor/addw -> c.and/c.or/c.xor/c.addw */ \ + if (do_compress()) { \ + Register src = noreg; \ + if (Rs1->is_compressed_valid() && Rs2->is_compressed_valid() && \ + ((src = Rs1, Rs2 == Rd) || (src = Rs2, Rs1 == Rd))) { \ + C_NAME(Rd, src); \ + return; \ + } \ + } \ + NORMAL_NAME(Rd, Rs1, Rs2); \ + } + + INSN(andr, c_and, _andr); + INSN(orr, c_or, _orr); + INSN(xorr, c_xor, _xorr); + INSN(addw, c_addw, _addw); + +#undef INSN + +private: +// some helper functions + bool do_compress() const { + return UseRVC && in_compressible_region(); + } + +#define FUNC(NAME, funct3, bits) \ + bool NAME(Register rs1, Register rd_rs2, int32_t imm12, bool ld) { \ + return rs1 == sp && \ + is_unsigned_imm_in_range(imm12, bits, 0) && \ + (intx(imm12) & funct3) == 0x0 && \ + (!ld || rd_rs2 != x0); \ + } \ + + FUNC(is_c_ldsdsp, 0b111, 9); + FUNC(is_c_lwswsp, 0b011, 8); + +#undef FUNC + +#define FUNC(NAME, funct3, bits) \ + bool NAME(Register rs1, int32_t imm12) { \ + return rs1 == sp && \ + is_unsigned_imm_in_range(imm12, bits, 0) && \ + (intx(imm12) & funct3) == 0x0; \ + } \ + + FUNC(is_c_fldsdsp, 0b111, 9); + +#undef FUNC + +#define FUNC(NAME, REG_TYPE, funct3, bits) \ + bool NAME(Register rs1, REG_TYPE rd_rs2, int32_t imm12) { \ + return rs1->is_compressed_valid() && \ + rd_rs2->is_compressed_valid() && \ + is_unsigned_imm_in_range(imm12, bits, 0) && \ + (intx(imm12) & funct3) == 0x0; \ + } \ + + FUNC(is_c_ldsd, Register, 0b111, 8); + FUNC(is_c_lwsw, Register, 0b011, 7); + FUNC(is_c_fldsd, FloatRegister, 0b111, 8); + +#undef FUNC + +public: +// -------------------------- +// Load/store register +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + /* lw -> c.lwsp/c.lw */ \ + if (do_compress()) { \ + if (is_c_lwswsp(Rs, Rd, offset, true)) { \ + c_lwsp(Rd, offset); \ + return; \ + } else if (is_c_lwsw(Rs, Rd, offset)) { \ + c_lw(Rd, Rs, offset); \ + return; \ + } \ + } \ + _lw(Rd, Rs, offset); \ + } + + INSN(lw); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + /* ld -> c.ldsp/c.ld */ \ + if (do_compress()) { \ + if (is_c_ldsdsp(Rs, Rd, offset, true)) { \ + c_ldsp(Rd, offset); \ + return; \ + } else if (is_c_ldsd(Rs, Rd, offset)) { \ + c_ld(Rd, Rs, offset); \ + return; \ + } \ + } \ + _ld(Rd, Rs, offset); \ + } + + INSN(ld); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \ + /* fld -> c.fldsp/c.fld */ \ + if (do_compress()) { \ + if (is_c_fldsdsp(Rs, offset)) { \ + c_fldsp(Rd, offset); \ + return; \ + } else if (is_c_fldsd(Rs, Rd, offset)) { \ + c_fld(Rd, Rs, offset); \ + return; \ + } \ + } \ + _fld(Rd, Rs, offset); \ + } + + INSN(fld); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + /* sd -> c.sdsp/c.sd */ \ + if (do_compress()) { \ + if (is_c_ldsdsp(Rs, Rd, offset, false)) { \ + c_sdsp(Rd, offset); \ + return; \ + } else if (is_c_ldsd(Rs, Rd, offset)) { \ + c_sd(Rd, Rs, offset); \ + return; \ + } \ + } \ + _sd(Rd, Rs, offset); \ + } + + INSN(sd); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + /* sw -> c.swsp/c.sw */ \ + if (do_compress()) { \ + if (is_c_lwswsp(Rs, Rd, offset, false)) { \ + c_swsp(Rd, offset); \ + return; \ + } else if (is_c_lwsw(Rs, Rd, offset)) { \ + c_sw(Rd, Rs, offset); \ + return; \ + } \ + } \ + _sw(Rd, Rs, offset); \ + } + + INSN(sw); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \ + /* fsd -> c.fsdsp/c.fsd */ \ + if (do_compress()) { \ + if (is_c_fldsdsp(Rs, offset)) { \ + c_fsdsp(Rd, offset); \ + return; \ + } else if (is_c_fldsd(Rs, Rd, offset)) { \ + c_fsd(Rd, Rs, offset); \ + return; \ + } \ + } \ + _fsd(Rd, Rs, offset); \ + } + + INSN(fsd); + +#undef INSN + +// -------------------------- +// Conditional branch instructions +// -------------------------- +#define INSN(NAME, C_NAME, NORMAL_NAME) \ + void NAME(Register Rs1, Register Rs2, const int64_t offset) { \ + /* beq/bne -> c.beqz/c.bnez */ \ + if (do_compress() && \ + (offset != 0 && Rs2 == x0 && Rs1->is_compressed_valid() && \ + is_imm_in_range(offset, 8, 1))) { \ + C_NAME(Rs1, offset); \ + return; \ + } \ + NORMAL_NAME(Rs1, Rs2, offset); \ + } + + INSN(beq, c_beqz, _beq); + INSN(bne, c_bnez, _bne); + +#undef INSN + +// -------------------------- +// Unconditional branch instructions +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, const int32_t offset) { \ + /* jal -> c.j */ \ + if (do_compress() && offset != 0 && Rd == x0 && is_imm_in_range(offset, 11, 1)) { \ + c_j(offset); \ + return; \ + } \ + _jal(Rd, offset); \ + } + + INSN(jal); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + /* jalr -> c.jr/c.jalr */ \ + if (do_compress() && (offset == 0 && Rs != x0)) { \ + if (Rd == x1) { \ + c_jalr(Rs); \ + return; \ + } else if (Rd == x0) { \ + c_jr(Rs); \ + return; \ + } \ + } \ + _jalr(Rd, Rs, offset); \ + } + + INSN(jalr); + +#undef INSN + +// -------------------------- +// Miscellaneous Instructions +// -------------------------- +#define INSN(NAME) \ + void NAME() { \ + /* ebreak -> c.ebreak */ \ + if (do_compress()) { \ + c_ebreak(); \ + return; \ + } \ + _ebreak(); \ + } + + INSN(ebreak); + +#undef INSN + +#define INSN(NAME) \ + void NAME() { \ + /* The illegal instruction in RVC is presented by a 16-bit 0. */ \ + if (do_compress()) { \ + emit_int16(0); \ + return; \ + } \ + _halt(); \ + } + + INSN(halt); + +#undef INSN + +// -------------------------- +// Immediate Instructions +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, int64_t imm) { \ + /* li -> c.li */ \ + if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) { \ + c_li(Rd, imm); \ + return; \ + } \ + _li(Rd, imm); \ + } + + INSN(li); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs1, int32_t imm) { \ + /* addi -> c.addi/c.nop/c.mv/c.addi16sp/c.addi4spn */ \ + if (do_compress()) { \ + if (Rd == Rs1 && is_imm_in_range(imm, 6, 0)) { \ + c_addi(Rd, imm); \ + return; \ + } else if (imm == 0 && Rd != x0 && Rs1 != x0) { \ + c_mv(Rd, Rs1); \ + return; \ + } else if (Rs1 == sp && imm != 0) { \ + if (Rd == Rs1 && (imm & 0b1111) == 0x0 && is_imm_in_range(imm, 10, 0)) { \ + c_addi16sp(imm); \ + return; \ + } else if (Rd->is_compressed_valid() && (imm & 0b11) == 0x0 && is_unsigned_imm_in_range(imm, 10, 0)) { \ + c_addi4spn(Rd, imm); \ + return; \ + } \ + } \ + } \ + _addi(Rd, Rs1, imm); \ + } + + INSN(addi); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs1, int32_t imm) { \ + /* addiw -> c.addiw */ \ + if (do_compress() && (Rd == Rs1 && Rd != x0 && is_imm_in_range(imm, 6, 0))) { \ + c_addiw(Rd, imm); \ + return; \ + } \ + _addiw(Rd, Rs1, imm); \ + } + + INSN(addiw); + +#undef INSN + +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs1, int32_t imm) { \ + /* and_imm12 -> c.andi */ \ + if (do_compress() && \ + (Rd == Rs1 && Rd->is_compressed_valid() && is_imm_in_range(imm, 6, 0))) { \ + c_andi(Rd, imm); \ + return; \ + } \ + _and_imm12(Rd, Rs1, imm); \ + } + + INSN(and_imm12); + +#undef INSN + +// -------------------------- +// Shift Immediate Instructions +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) { \ + /* slli -> c.slli */ \ + if (do_compress() && (Rd == Rs1 && Rd != x0 && shamt != 0)) { \ + c_slli(Rd, shamt); \ + return; \ + } \ + _slli(Rd, Rs1, shamt); \ + } + + INSN(slli); + +#undef INSN + +// -------------------------- +#define INSN(NAME, C_NAME, NORMAL_NAME) \ + void NAME(Register Rd, Register Rs1, unsigned shamt) { \ + /* srai/srli -> c.srai/c.srli */ \ + if (do_compress() && (Rd == Rs1 && Rd->is_compressed_valid() && shamt != 0)) { \ + C_NAME(Rd, shamt); \ + return; \ + } \ + NORMAL_NAME(Rd, Rs1, shamt); \ + } + + INSN(srai, c_srai, _srai); + INSN(srli, c_srli, _srli); + +#undef INSN + +// -------------------------- +// Upper Immediate Instruction +// -------------------------- +#define INSN(NAME) \ + void NAME(Register Rd, int32_t imm) { \ + /* lui -> c.lui */ \ + if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_imm_in_range(imm, 18, 0))) { \ + c_lui(Rd, imm); \ + return; \ + } \ + _lui(Rd, imm); \ + } + + INSN(lui); + +#undef INSN + +// --------------------------------------------------------------------------------------- + + void bgt(Register Rs, Register Rt, const address &dest); + void ble(Register Rs, Register Rt, const address &dest); + void bgtu(Register Rs, Register Rt, const address &dest); + void bleu(Register Rs, Register Rt, const address &dest); + void bgt(Register Rs, Register Rt, Label &l, bool is_far = false); + void ble(Register Rs, Register Rt, Label &l, bool is_far = false); + void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false); + void bleu(Register Rs, Register Rt, Label &l, bool is_far = false); + + typedef void (Assembler::* jal_jalr_insn)(Register Rt, address dest); + typedef void (Assembler::* load_insn_by_temp)(Register Rt, address dest, Register temp); + typedef void (Assembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest); + typedef void (Assembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far); + + void wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn, + compare_and_branch_label_insn neg_insn, bool is_far); + void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn); + void wrap_label(Register r, Label &L, jal_jalr_insn insn); + + // calculate pseudoinstruction + void add(Register Rd, Register Rn, int64_t increment, Register temp = t0); + void addw(Register Rd, Register Rn, int64_t increment, Register temp = t0); + void sub(Register Rd, Register Rn, int64_t decrement, Register temp = t0); + void subw(Register Rd, Register Rn, int64_t decrement, Register temp = t0); + + // RVB pseudo instructions + // zero extend word + void zext_w(Register Rd, Register Rs); + + Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) { + } + + // Stack overflow checking + virtual void bang_stack_with_offset(int offset) { Unimplemented(); } + + static bool operand_valid_for_add_immediate(long imm) { + return is_imm_in_range(imm, 12, 0); + } + + // The maximum range of a branch is fixed for the RISCV architecture. + static const unsigned long branch_range = 1 * M; + + static bool reachable_from_branch_at(address branch, address target) { + return uabs(target - branch) < branch_range; + } + + virtual ~Assembler() {} +}; + +#endif // CPU_RISCV_ASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7ffe8803985d00121c88ccdc81999b65857a46bb --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP +#define CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP + +#include "asm/assembler.inline.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + +inline bool is_imm_in_range(long value, unsigned bits, unsigned align_bits) { + intx sign_bits = (value >> (bits + align_bits - 1)); + return ((value & right_n_bits(align_bits)) == 0) && ((sign_bits == 0) || (sign_bits == -1)); +} + +inline bool is_unsigned_imm_in_range(intx value, unsigned bits, unsigned align_bits) { + return (value >= 0) && ((value & right_n_bits(align_bits)) == 0) && ((value >> (align_bits + bits)) == 0); +} + +inline bool is_offset_in_range(intx offset, unsigned bits) { + return is_imm_in_range(offset, bits, 0); +} + +#endif // CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/bytes_riscv.hpp b/src/hotspot/cpu/riscv/bytes_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..23d982f9abd3d000d16aaf95691e077e8e502278 --- /dev/null +++ b/src/hotspot/cpu/riscv/bytes_riscv.hpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_BYTES_RISCV_HPP +#define CPU_RISCV_BYTES_RISCV_HPP + +#include "memory/allStatic.hpp" + +class Bytes: AllStatic { + public: + // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering + // RISCV needs to check for alignment. + + // Forward declarations of the compiler-dependent implementation + static inline u2 swap_u2(u2 x); + static inline u4 swap_u4(u4 x); + static inline u8 swap_u8(u8 x); + + static inline u2 get_native_u2(address p) { + if ((intptr_t(p) & 1) == 0) { + return *(u2*)p; + } else { + return ((u2)(p[1]) << 8) | + ((u2)(p[0])); + } + } + + static inline u4 get_native_u4(address p) { + switch (intptr_t(p) & 3) { + case 0: + return *(u4*)p; + + case 2: + return ((u4)(((u2*)p)[1]) << 16) | + ((u4)(((u2*)p)[0])); + + default: + return ((u4)(p[3]) << 24) | + ((u4)(p[2]) << 16) | + ((u4)(p[1]) << 8) | + ((u4)(p[0])); + } + } + + static inline u8 get_native_u8(address p) { + switch (intptr_t(p) & 7) { + case 0: + return *(u8*)p; + + case 4: + return ((u8)(((u4*)p)[1]) << 32) | + ((u8)(((u4*)p)[0])); + + case 2: + return ((u8)(((u2*)p)[3]) << 48) | + ((u8)(((u2*)p)[2]) << 32) | + ((u8)(((u2*)p)[1]) << 16) | + ((u8)(((u2*)p)[0])); + + default: + return ((u8)(p[7]) << 56) | + ((u8)(p[6]) << 48) | + ((u8)(p[5]) << 40) | + ((u8)(p[4]) << 32) | + ((u8)(p[3]) << 24) | + ((u8)(p[2]) << 16) | + ((u8)(p[1]) << 8) | + ((u8)(p[0])); + } + } + + static inline void put_native_u2(address p, u2 x) { + if ((intptr_t(p) & 1) == 0) { + *(u2*)p = x; + } else { + p[1] = x >> 8; + p[0] = x; + } + } + + static inline void put_native_u4(address p, u4 x) { + switch (intptr_t(p) & 3) { + case 0: + *(u4*)p = x; + break; + + case 2: + ((u2*)p)[1] = x >> 16; + ((u2*)p)[0] = x; + break; + + default: + ((u1*)p)[3] = x >> 24; + ((u1*)p)[2] = x >> 16; + ((u1*)p)[1] = x >> 8; + ((u1*)p)[0] = x; + break; + } + } + + static inline void put_native_u8(address p, u8 x) { + switch (intptr_t(p) & 7) { + case 0: + *(u8*)p = x; + break; + + case 4: + ((u4*)p)[1] = x >> 32; + ((u4*)p)[0] = x; + break; + + case 2: + ((u2*)p)[3] = x >> 48; + ((u2*)p)[2] = x >> 32; + ((u2*)p)[1] = x >> 16; + ((u2*)p)[0] = x; + break; + + default: + ((u1*)p)[7] = x >> 56; + ((u1*)p)[6] = x >> 48; + ((u1*)p)[5] = x >> 40; + ((u1*)p)[4] = x >> 32; + ((u1*)p)[3] = x >> 24; + ((u1*)p)[2] = x >> 16; + ((u1*)p)[1] = x >> 8; + ((u1*)p)[0] = x; + break; + } + } + + // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) + static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); } + static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); } + static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); } + + static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); } + static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); } + static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); } +}; + +#include OS_CPU_HEADER(bytes) + +#endif // CPU_RISCV_BYTES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dcd0472c540fb7e315767a803c62b84683c93c81 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "c1/c1_CodeStubs.hpp" +#include "c1/c1_FrameMap.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" +#include "nativeInst_riscv.hpp" +#include "runtime/sharedRuntime.hpp" +#include "vmreg_riscv.inline.hpp" + + +#define __ ce->masm()-> + +void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset()); + __ code_section()->relocate(__ pc(), safepoint_pc.rspec()); + __ la(t0, safepoint_pc.target()); + __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); + + assert(SharedRuntime::polling_page_return_handler_blob() != NULL, + "polling page return stub not created yet"); + address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); + + __ far_jump(RuntimeAddress(stub)); +} + +void CounterOverflowStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + Metadata *m = _method->as_constant_ptr()->as_metadata(); + __ mov_metadata(t0, m); + ce->store_parameter(t0, 1); + ce->store_parameter(_bci, 0); + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::counter_overflow_id))); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + __ j(_continuation); +} + +RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array) + : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) { + assert(info != NULL, "must have info"); + _info = new CodeEmitInfo(info); +} + +RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index) + : _index(index), _array(), _throw_index_out_of_bounds_exception(true) { + assert(info != NULL, "must have info"); + _info = new CodeEmitInfo(info); +} + +void RangeCheckStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + if (_info->deoptimize_on_exception()) { + address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id); + __ far_call(RuntimeAddress(a)); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + debug_only(__ should_not_reach_here()); + return; + } + + if (_index->is_cpu_register()) { + __ mv(t0, _index->as_register()); + } else { + __ mv(t0, _index->as_jint()); + } + Runtime1::StubID stub_id; + if (_throw_index_out_of_bounds_exception) { + stub_id = Runtime1::throw_index_exception_id; + } else { + assert(_array != LIR_Opr::nullOpr(), "sanity"); + __ mv(t1, _array->as_pointer_register()); + stub_id = Runtime1::throw_range_check_failed_id; + } + int32_t off = 0; + __ la_patchable(ra, RuntimeAddress(Runtime1::entry_for(stub_id)), off); + __ jalr(ra, ra, off); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + debug_only(__ should_not_reach_here()); +} + +PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { + _info = new CodeEmitInfo(info); +} + +void PredicateFailedStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id); + __ far_call(RuntimeAddress(a)); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + debug_only(__ should_not_reach_here()); +} + +void DivByZeroStub::emit_code(LIR_Assembler* ce) { + if (_offset != -1) { + ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); + } + __ bind(_entry); + __ far_call(Address(Runtime1::entry_for(Runtime1::throw_div0_exception_id), relocInfo::runtime_call_type)); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); +#ifdef ASSERT + __ should_not_reach_here(); +#endif +} + +// Implementation of NewInstanceStub +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id) { + _result = result; + _klass = klass; + _klass_reg = klass_reg; + _info = new CodeEmitInfo(info); + assert(stub_id == Runtime1::new_instance_id || + stub_id == Runtime1::fast_new_instance_id || + stub_id == Runtime1::fast_new_instance_init_check_id, + "need new_instance id"); + _stub_id = stub_id; +} + +void NewInstanceStub::emit_code(LIR_Assembler* ce) { + assert(__ rsp_offset() == 0, "frame size should be fixed"); + __ bind(_entry); + __ mv(x13, _klass_reg->as_register()); + __ far_call(RuntimeAddress(Runtime1::entry_for(_stub_id))); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + assert(_result->as_register() == x10, "result must in x10"); + __ j(_continuation); +} + +// Implementation of NewTypeArrayStub +NewTypeArrayStub::NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) { + _klass_reg = klass_reg; + _length = length; + _result = result; + _info = new CodeEmitInfo(info); +} + +void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { + assert(__ rsp_offset() == 0, "frame size should be fixed"); + __ bind(_entry); + assert(_length->as_register() == x9, "length must in x9"); + assert(_klass_reg->as_register() == x13, "klass_reg must in x13"); + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_type_array_id))); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + assert(_result->as_register() == x10, "result must in x10"); + __ j(_continuation); +} + +// Implementation of NewObjectArrayStub +NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) { + _klass_reg = klass_reg; + _result = result; + _length = length; + _info = new CodeEmitInfo(info); +} + +void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { + assert(__ rsp_offset() == 0, "frame size should be fixed"); + __ bind(_entry); + assert(_length->as_register() == x9, "length must in x9"); + assert(_klass_reg->as_register() == x13, "klass_reg must in x13"); + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id))); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + assert(_result->as_register() == x10, "result must in x10"); + __ j(_continuation); +} + +// Implementation of MonitorAccessStubs +MonitorEnterStub::MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info) +: MonitorAccessStub(obj_reg, lock_reg) { + _info = new CodeEmitInfo(info); +} + +void MonitorEnterStub::emit_code(LIR_Assembler* ce) { + assert(__ rsp_offset() == 0, "frame size should be fixed"); + __ bind(_entry); + ce->store_parameter(_obj_reg->as_register(), 1); + ce->store_parameter(_lock_reg->as_register(), 0); + Runtime1::StubID enter_id; + if (ce->compilation()->has_fpu_code()) { + enter_id = Runtime1::monitorenter_id; + } else { + enter_id = Runtime1::monitorenter_nofpu_id; + } + __ far_call(RuntimeAddress(Runtime1::entry_for(enter_id))); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + __ j(_continuation); +} + +void MonitorExitStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + if (_compute_lock) { + // lock_reg was destroyed by fast unlocking attempt => recompute it + ce->monitor_address(_monitor_ix, _lock_reg); + } + ce->store_parameter(_lock_reg->as_register(), 0); + // note: non-blocking leaf routine => no call info needed + Runtime1::StubID exit_id; + if (ce->compilation()->has_fpu_code()) { + exit_id = Runtime1::monitorexit_id; + } else { + exit_id = Runtime1::monitorexit_nofpu_id; + } + __ la(ra, _continuation); + __ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id))); +} + +// Implementation of patching: +// - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes) +// - Replace original code with a call to the stub +// At Runtime: +// - call to stub, jump to runtime +// - in runtime: preserve all registers (rspecially objects, i.e., source and destination object) +// - in runtime: after initializing class, restore original code, reexecute instruction + +int PatchingStub::_patch_info_offset = -NativeGeneralJump::instruction_size; + +void PatchingStub::align_patch_site(MacroAssembler* masm) {} + +void PatchingStub::emit_code(LIR_Assembler* ce) { + assert(false, "RISCV should not use C1 runtime patching"); +} + +void DeoptimizeStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + ce->store_parameter(_trap_request, 0); + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::deoptimize_id))); + ce->add_call_info_here(_info); + DEBUG_ONLY(__ should_not_reach_here()); +} + +void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { + address a = NULL; + if (_info->deoptimize_on_exception()) { + // Deoptimize, do not throw the exception, because it is probably wrong to do it here. + a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id); + } else { + a = Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id); + } + + ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); + __ bind(_entry); + __ far_call(RuntimeAddress(a)); + ce->add_call_info_here(_info); + ce->verify_oop_map(_info); + debug_only(__ should_not_reach_here()); +} + +void SimpleExceptionStub::emit_code(LIR_Assembler* ce) { + assert(__ rsp_offset() == 0, "frame size should be fixed"); + + __ bind(_entry); + // pass the object in a tmp register because all other registers + // must be preserved + if (_obj->is_cpu_register()) { + __ mv(t0, _obj->as_register()); + } + __ far_call(RuntimeAddress(Runtime1::entry_for(_stub)), NULL, t1); + ce->add_call_info_here(_info); + debug_only(__ should_not_reach_here()); +} + +void ArrayCopyStub::emit_code(LIR_Assembler* ce) { + // ---------------slow case: call to native----------------- + __ bind(_entry); + // Figure out where the args should go + // This should really convert the IntrinsicID to the Method* and signature + // but I don't know how to do that. + const int args_num = 5; + VMRegPair args[args_num]; + BasicType signature[args_num] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT }; + SharedRuntime::java_calling_convention(signature, args, args_num); + + // push parameters + Register r[args_num]; + r[0] = src()->as_register(); + r[1] = src_pos()->as_register(); + r[2] = dst()->as_register(); + r[3] = dst_pos()->as_register(); + r[4] = length()->as_register(); + + // next registers will get stored on the stack + for (int j = 0; j < args_num; j++) { + VMReg r_1 = args[j].first(); + if (r_1->is_stack()) { + int st_off = r_1->reg2stack() * wordSize; + __ sd(r[j], Address(sp, st_off)); + } else { + assert(r[j] == args[j].first()->as_Register(), "Wrong register for arg"); + } + } + + ce->align_call(lir_static_call); + + ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } + Address resolve(SharedRuntime::get_resolve_static_call_stub(), + relocInfo::static_call_type); + address call = __ trampoline_call(resolve); + if (call == NULL) { + ce->bailout("trampoline stub overflow"); + return; + } + ce->add_call_info_here(info()); + +#ifndef PRODUCT + if (PrintC1Statistics) { + __ la(t1, ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt)); + __ add_memory_int32(Address(t1), 1); + } +#endif + + __ j(_continuation); +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4417ad6309124c55268ac3d127f6ff904dc5da0f --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_DEFS_RISCV_HPP +#define CPU_RISCV_C1_DEFS_RISCV_HPP + +// native word offsets from memory address (little endian) +enum { + pd_lo_word_offset_in_bytes = 0, + pd_hi_word_offset_in_bytes = BytesPerWord +}; + +// explicit rounding operations are required to implement the strictFP mode +enum { + pd_strict_fp_requires_explicit_rounding = false +}; + +// registers +enum { + pd_nof_cpu_regs_frame_map = RegisterImpl::number_of_registers, // number of registers used during code emission + pd_nof_fpu_regs_frame_map = FloatRegisterImpl::number_of_registers, // number of float registers used during code emission + + // caller saved + pd_nof_caller_save_cpu_regs_frame_map = 13, // number of registers killed by calls + pd_nof_caller_save_fpu_regs_frame_map = 32, // number of float registers killed by calls + + pd_first_callee_saved_reg = pd_nof_caller_save_cpu_regs_frame_map, + pd_last_callee_saved_reg = 21, + + pd_last_allocatable_cpu_reg = pd_nof_caller_save_cpu_regs_frame_map - 1, + + pd_nof_cpu_regs_reg_alloc + = pd_nof_caller_save_cpu_regs_frame_map, // number of registers that are visible to register allocator + pd_nof_fpu_regs_reg_alloc = 32, // number of float registers that are visible to register allocator + + pd_nof_cpu_regs_linearscan = 32, // number of registers visible to linear scan + pd_nof_fpu_regs_linearscan = pd_nof_fpu_regs_frame_map, // number of float registers visible to linear scan + pd_nof_xmm_regs_linearscan = 0, // don't have vector registers + + pd_first_cpu_reg = 0, + pd_last_cpu_reg = pd_nof_cpu_regs_reg_alloc - 1, + pd_first_byte_reg = 0, + pd_last_byte_reg = pd_nof_cpu_regs_reg_alloc - 1, + + pd_first_fpu_reg = pd_nof_cpu_regs_frame_map, + pd_last_fpu_reg = pd_first_fpu_reg + 31, + + pd_first_callee_saved_fpu_reg_1 = 8 + pd_first_fpu_reg, + pd_last_callee_saved_fpu_reg_1 = 9 + pd_first_fpu_reg, + pd_first_callee_saved_fpu_reg_2 = 18 + pd_first_fpu_reg, + pd_last_callee_saved_fpu_reg_2 = 27 + pd_first_fpu_reg +}; + + +// Encoding of float value in debug info. This is true on x86 where +// floats are extended to doubles when stored in the stack, false for +// RISCV where floats and doubles are stored in their native form. +enum { + pd_float_saved_as_double = false +}; + +#endif // CPU_RISCV_C1_DEFS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3a2606c5323b847d6ccc8599523a1b159db0d2d --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +//-------------------------------------------------------- +// FpuStackSim +//-------------------------------------------------------- + +// No FPU stack on RISCV diff --git a/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7bc3d3115018e47c612c31430228ce28ea143b62 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_FPUSTACKSIM_RISCV_HPP +#define CPU_RISCV_C1_FPUSTACKSIM_RISCV_HPP + +// No FPU stack on RISCV +class FpuStackSim; + +#endif // CPU_RISCV_C1_FPUSTACKSIM_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..172031941b2b0d9890f3f0ced8b57067d8aa9f1a --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_FrameMap.hpp" +#include "c1/c1_LIR.hpp" +#include "runtime/sharedRuntime.hpp" +#include "vmreg_riscv.inline.hpp" + +LIR_Opr FrameMap::map_to_opr(BasicType type, VMRegPair* reg, bool) { + LIR_Opr opr = LIR_OprFact::illegalOpr; + VMReg r_1 = reg->first(); + VMReg r_2 = reg->second(); + if (r_1->is_stack()) { + // Convert stack slot to an SP offset + // The calling convention does not count the SharedRuntime::out_preserve_stack_slots() value + // so we must add it in here. + int st_off = (r_1->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; + opr = LIR_OprFact::address(new LIR_Address(sp_opr, st_off, type)); + } else if (r_1->is_Register()) { + Register reg1 = r_1->as_Register(); + if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) { + Register reg2 = r_2->as_Register(); + assert(reg2 == reg1, "must be same register"); + opr = as_long_opr(reg1); + } else if (is_reference_type(type)) { + opr = as_oop_opr(reg1); + } else if (type == T_METADATA) { + opr = as_metadata_opr(reg1); + } else if (type == T_ADDRESS) { + opr = as_address_opr(reg1); + } else { + opr = as_opr(reg1); + } + } else if (r_1->is_FloatRegister()) { + assert(type == T_DOUBLE || type == T_FLOAT, "wrong type"); + int num = r_1->as_FloatRegister()->encoding(); + if (type == T_FLOAT) { + opr = LIR_OprFact::single_fpu(num); + } else { + opr = LIR_OprFact::double_fpu(num); + } + } else { + ShouldNotReachHere(); + } + return opr; +} + +LIR_Opr FrameMap::zr_opr; +LIR_Opr FrameMap::r1_opr; +LIR_Opr FrameMap::r2_opr; +LIR_Opr FrameMap::r3_opr; +LIR_Opr FrameMap::r4_opr; +LIR_Opr FrameMap::r5_opr; +LIR_Opr FrameMap::r6_opr; +LIR_Opr FrameMap::r7_opr; +LIR_Opr FrameMap::r8_opr; +LIR_Opr FrameMap::r9_opr; +LIR_Opr FrameMap::r10_opr; +LIR_Opr FrameMap::r11_opr; +LIR_Opr FrameMap::r12_opr; +LIR_Opr FrameMap::r13_opr; +LIR_Opr FrameMap::r14_opr; +LIR_Opr FrameMap::r15_opr; +LIR_Opr FrameMap::r16_opr; +LIR_Opr FrameMap::r17_opr; +LIR_Opr FrameMap::r18_opr; +LIR_Opr FrameMap::r19_opr; +LIR_Opr FrameMap::r20_opr; +LIR_Opr FrameMap::r21_opr; +LIR_Opr FrameMap::r22_opr; +LIR_Opr FrameMap::r23_opr; +LIR_Opr FrameMap::r24_opr; +LIR_Opr FrameMap::r25_opr; +LIR_Opr FrameMap::r26_opr; +LIR_Opr FrameMap::r27_opr; +LIR_Opr FrameMap::r28_opr; +LIR_Opr FrameMap::r29_opr; +LIR_Opr FrameMap::r30_opr; +LIR_Opr FrameMap::r31_opr; + +LIR_Opr FrameMap::fp_opr; +LIR_Opr FrameMap::sp_opr; + +LIR_Opr FrameMap::receiver_opr; + +LIR_Opr FrameMap::zr_oop_opr; +LIR_Opr FrameMap::r1_oop_opr; +LIR_Opr FrameMap::r2_oop_opr; +LIR_Opr FrameMap::r3_oop_opr; +LIR_Opr FrameMap::r4_oop_opr; +LIR_Opr FrameMap::r5_oop_opr; +LIR_Opr FrameMap::r6_oop_opr; +LIR_Opr FrameMap::r7_oop_opr; +LIR_Opr FrameMap::r8_oop_opr; +LIR_Opr FrameMap::r9_oop_opr; +LIR_Opr FrameMap::r10_oop_opr; +LIR_Opr FrameMap::r11_oop_opr; +LIR_Opr FrameMap::r12_oop_opr; +LIR_Opr FrameMap::r13_oop_opr; +LIR_Opr FrameMap::r14_oop_opr; +LIR_Opr FrameMap::r15_oop_opr; +LIR_Opr FrameMap::r16_oop_opr; +LIR_Opr FrameMap::r17_oop_opr; +LIR_Opr FrameMap::r18_oop_opr; +LIR_Opr FrameMap::r19_oop_opr; +LIR_Opr FrameMap::r20_oop_opr; +LIR_Opr FrameMap::r21_oop_opr; +LIR_Opr FrameMap::r22_oop_opr; +LIR_Opr FrameMap::r23_oop_opr; +LIR_Opr FrameMap::r24_oop_opr; +LIR_Opr FrameMap::r25_oop_opr; +LIR_Opr FrameMap::r26_oop_opr; +LIR_Opr FrameMap::r27_oop_opr; +LIR_Opr FrameMap::r28_oop_opr; +LIR_Opr FrameMap::r29_oop_opr; +LIR_Opr FrameMap::r30_oop_opr; +LIR_Opr FrameMap::r31_oop_opr; + +LIR_Opr FrameMap::t0_opr; +LIR_Opr FrameMap::t1_opr; +LIR_Opr FrameMap::t0_long_opr; +LIR_Opr FrameMap::t1_long_opr; + +LIR_Opr FrameMap::r10_metadata_opr; +LIR_Opr FrameMap::r11_metadata_opr; +LIR_Opr FrameMap::r12_metadata_opr; +LIR_Opr FrameMap::r13_metadata_opr; +LIR_Opr FrameMap::r14_metadata_opr; +LIR_Opr FrameMap::r15_metadata_opr; + +LIR_Opr FrameMap::long10_opr; +LIR_Opr FrameMap::long11_opr; +LIR_Opr FrameMap::fpu10_float_opr; +LIR_Opr FrameMap::fpu10_double_opr; + +LIR_Opr FrameMap::_caller_save_cpu_regs[] = {}; +LIR_Opr FrameMap::_caller_save_fpu_regs[] = {}; + +//-------------------------------------------------------- +// FrameMap +//-------------------------------------------------------- +// |---f31--| +// |---..---| +// |---f28--| +// |---f27--|<---pd_last_callee_saved_fpu_reg_2 +// |---..---| +// |---f18--|<---pd_first_callee_saved_fpu_reg_2 +// |---f17--| +// |---..---| +// |---f10--| +// |---f9---|<---pd_last_callee_saved_fpu_reg_1 +// |---f8---|<---pd_first_callee_saved_fpu_reg_1 +// |---f7---| +// |---..---| +// |---f0---| +// |---x27--| +// |---x23--| +// |---x8---| +// |---x4---| +// |---x3---| +// |---x2---| +// |---x1---| +// |---x0---| +// |---x26--|<---pd_last_callee_saved_reg +// |---..---| +// |---x18--| +// |---x9---|<---pd_first_callee_saved_reg +// |---x31--| +// |---..---| +// |---x28--| +// |---x17--| +// |---..---| +// |---x10--| +// |---x7---| + +void FrameMap::initialize() { + assert(!_init_done, "once"); + + int i = 0; + + // caller save register + map_register(i, x7); r7_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x10); r10_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x11); r11_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x12); r12_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x13); r13_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x14); r14_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x15); r15_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x16); r16_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x17); r17_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x28); r28_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x29); r29_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x30); r30_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x31); r31_opr = LIR_OprFact::single_cpu(i); i++; + + // callee save register + map_register(i, x9); r9_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x18); r18_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x19); r19_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x20); r20_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x21); r21_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x22); r22_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x24); r24_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x25); r25_opr = LIR_OprFact::single_cpu(i); i++; + map_register(i, x26); r26_opr = LIR_OprFact::single_cpu(i); i++; + + // special register + map_register(i, x0); zr_opr = LIR_OprFact::single_cpu(i); i++; // zr + map_register(i, x1); r1_opr = LIR_OprFact::single_cpu(i); i++; // ra + map_register(i, x2); r2_opr = LIR_OprFact::single_cpu(i); i++; // sp + map_register(i, x3); r3_opr = LIR_OprFact::single_cpu(i); i++; // gp + map_register(i, x4); r4_opr = LIR_OprFact::single_cpu(i); i++; // thread + map_register(i, x8); r8_opr = LIR_OprFact::single_cpu(i); i++; // fp + map_register(i, x23); r23_opr = LIR_OprFact::single_cpu(i); i++; // java thread + map_register(i, x27); r27_opr = LIR_OprFact::single_cpu(i); i++; // heapbase + + // tmp register + map_register(i, x5); r5_opr = LIR_OprFact::single_cpu(i); i++; // t0 + map_register(i, x6); r6_opr = LIR_OprFact::single_cpu(i); i++; // t1 + + t0_opr = r5_opr; + t1_opr = r6_opr; + t0_long_opr = LIR_OprFact::double_cpu(r5_opr->cpu_regnr(), r5_opr->cpu_regnr()); + t1_long_opr = LIR_OprFact::double_cpu(r6_opr->cpu_regnr(), r6_opr->cpu_regnr()); + + long10_opr = LIR_OprFact::double_cpu(r10_opr->cpu_regnr(), r10_opr->cpu_regnr()); + long11_opr = LIR_OprFact::double_cpu(r11_opr->cpu_regnr(), r11_opr->cpu_regnr()); + + fpu10_float_opr = LIR_OprFact::single_fpu(10); + fpu10_double_opr = LIR_OprFact::double_fpu(10); + + i = 0; + _caller_save_cpu_regs[i++] = r7_opr; + _caller_save_cpu_regs[i++] = r10_opr; + _caller_save_cpu_regs[i++] = r11_opr; + _caller_save_cpu_regs[i++] = r12_opr; + _caller_save_cpu_regs[i++] = r13_opr; + _caller_save_cpu_regs[i++] = r14_opr; + _caller_save_cpu_regs[i++] = r15_opr; + _caller_save_cpu_regs[i++] = r16_opr; + _caller_save_cpu_regs[i++] = r17_opr; + _caller_save_cpu_regs[i++] = r28_opr; + _caller_save_cpu_regs[i++] = r29_opr; + _caller_save_cpu_regs[i++] = r30_opr; + _caller_save_cpu_regs[i++] = r31_opr; + + _init_done = true; + + zr_oop_opr = as_oop_opr(x0); + r1_oop_opr = as_oop_opr(x1); + r2_oop_opr = as_oop_opr(x2); + r3_oop_opr = as_oop_opr(x3); + r4_oop_opr = as_oop_opr(x4); + r5_oop_opr = as_oop_opr(x5); + r6_oop_opr = as_oop_opr(x6); + r7_oop_opr = as_oop_opr(x7); + r8_oop_opr = as_oop_opr(x8); + r9_oop_opr = as_oop_opr(x9); + r10_oop_opr = as_oop_opr(x10); + r11_oop_opr = as_oop_opr(x11); + r12_oop_opr = as_oop_opr(x12); + r13_oop_opr = as_oop_opr(x13); + r14_oop_opr = as_oop_opr(x14); + r15_oop_opr = as_oop_opr(x15); + r16_oop_opr = as_oop_opr(x16); + r17_oop_opr = as_oop_opr(x17); + r18_oop_opr = as_oop_opr(x18); + r19_oop_opr = as_oop_opr(x19); + r20_oop_opr = as_oop_opr(x20); + r21_oop_opr = as_oop_opr(x21); + r22_oop_opr = as_oop_opr(x22); + r23_oop_opr = as_oop_opr(x23); + r24_oop_opr = as_oop_opr(x24); + r25_oop_opr = as_oop_opr(x25); + r26_oop_opr = as_oop_opr(x26); + r27_oop_opr = as_oop_opr(x27); + r28_oop_opr = as_oop_opr(x28); + r29_oop_opr = as_oop_opr(x29); + r30_oop_opr = as_oop_opr(x30); + r31_oop_opr = as_oop_opr(x31); + + r10_metadata_opr = as_metadata_opr(x10); + r11_metadata_opr = as_metadata_opr(x11); + r12_metadata_opr = as_metadata_opr(x12); + r13_metadata_opr = as_metadata_opr(x13); + r14_metadata_opr = as_metadata_opr(x14); + r15_metadata_opr = as_metadata_opr(x15); + + sp_opr = as_pointer_opr(sp); + fp_opr = as_pointer_opr(fp); + + VMRegPair regs; + BasicType sig_bt = T_OBJECT; + SharedRuntime::java_calling_convention(&sig_bt, ®s, 1); + receiver_opr = as_oop_opr(regs.first()->as_Register()); + + for (i = 0; i < nof_caller_save_fpu_regs; i++) { + _caller_save_fpu_regs[i] = LIR_OprFact::single_fpu(i); + } +} + + +Address FrameMap::make_new_address(ByteSize sp_offset) const { + return Address(sp, in_bytes(sp_offset)); +} + + +// ----------------mapping----------------------- +// all mapping is based on fp addressing, except for simple leaf methods where we access +// the locals sp based (and no frame is built) + + +// Frame for simple leaf methods (quick entries) +// +// +----------+ +// | ret addr | <- TOS +// +----------+ +// | args | +// | ...... | + +// Frame for standard methods +// +// | .........| <- TOS +// | locals | +// +----------+ +// | old fp, | +// +----------+ +// | ret addr | +// +----------+ +// | args | <- FP +// | .........| + + +// For OopMaps, map a local variable or spill index to an VMRegImpl name. +// This is the offset from sp() in the frame of the slot for the index, +// skewed by VMRegImpl::stack0 to indicate a stack location (vs.a register.) +// +// framesize + +// stack0 stack0 0 <- VMReg +// | | | +// ...........|..............|.............| +// 0 1 2 3 x x 4 5 6 ... | <- local indices +// ^ ^ sp() ( x x indicate link +// | | and return addr) +// arguments non-argument locals + + +VMReg FrameMap::fpu_regname (int n) { + // Return the OptoReg name for the fpu stack slot "n" + // A spilled fpu stack slot comprises to two single-word OptoReg's. + return as_FloatRegister(n)->as_VMReg(); +} + +LIR_Opr FrameMap::stack_pointer() { + return FrameMap::sp_opr; +} + +// JSR 292 +LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { + return LIR_OprFact::illegalOpr; // Not needed on riscv +} + +bool FrameMap::validate_frame() { + return true; +} diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..01281f5c9e1611d85fe8fa1ddd993a1378b85a78 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_FRAMEMAP_RISCV_HPP +#define CPU_RISCV_C1_FRAMEMAP_RISCV_HPP + +// On RISCV the frame looks as follows: +// +// +-----------------------------+---------+----------------------------------------+----------------+----------- +// | size_arguments-nof_reg_args | 2 words | size_locals-size_arguments+numreg_args | _size_monitors | spilling . +// +-----------------------------+---------+----------------------------------------+----------------+----------- + + public: + static const int pd_c_runtime_reserved_arg_size; + + enum { + first_available_sp_in_frame = 0, + frame_pad_in_bytes = 16, + nof_reg_args = 8 + }; + + public: + static LIR_Opr receiver_opr; + + static LIR_Opr zr_opr; + static LIR_Opr r1_opr; + static LIR_Opr r2_opr; + static LIR_Opr r3_opr; + static LIR_Opr r4_opr; + static LIR_Opr r5_opr; + static LIR_Opr r6_opr; + static LIR_Opr r7_opr; + static LIR_Opr r8_opr; + static LIR_Opr r9_opr; + static LIR_Opr r10_opr; + static LIR_Opr r11_opr; + static LIR_Opr r12_opr; + static LIR_Opr r13_opr; + static LIR_Opr r14_opr; + static LIR_Opr r15_opr; + static LIR_Opr r16_opr; + static LIR_Opr r17_opr; + static LIR_Opr r18_opr; + static LIR_Opr r19_opr; + static LIR_Opr r20_opr; + static LIR_Opr r21_opr; + static LIR_Opr r22_opr; + static LIR_Opr r23_opr; + static LIR_Opr r24_opr; + static LIR_Opr r25_opr; + static LIR_Opr r26_opr; + static LIR_Opr r27_opr; + static LIR_Opr r28_opr; + static LIR_Opr r29_opr; + static LIR_Opr r30_opr; + static LIR_Opr r31_opr; + static LIR_Opr fp_opr; + static LIR_Opr sp_opr; + + static LIR_Opr zr_oop_opr; + static LIR_Opr r1_oop_opr; + static LIR_Opr r2_oop_opr; + static LIR_Opr r3_oop_opr; + static LIR_Opr r4_oop_opr; + static LIR_Opr r5_oop_opr; + static LIR_Opr r6_oop_opr; + static LIR_Opr r7_oop_opr; + static LIR_Opr r8_oop_opr; + static LIR_Opr r9_oop_opr; + static LIR_Opr r10_oop_opr; + static LIR_Opr r11_oop_opr; + static LIR_Opr r12_oop_opr; + static LIR_Opr r13_oop_opr; + static LIR_Opr r14_oop_opr; + static LIR_Opr r15_oop_opr; + static LIR_Opr r16_oop_opr; + static LIR_Opr r17_oop_opr; + static LIR_Opr r18_oop_opr; + static LIR_Opr r19_oop_opr; + static LIR_Opr r20_oop_opr; + static LIR_Opr r21_oop_opr; + static LIR_Opr r22_oop_opr; + static LIR_Opr r23_oop_opr; + static LIR_Opr r24_oop_opr; + static LIR_Opr r25_oop_opr; + static LIR_Opr r26_oop_opr; + static LIR_Opr r27_oop_opr; + static LIR_Opr r28_oop_opr; + static LIR_Opr r29_oop_opr; + static LIR_Opr r30_oop_opr; + static LIR_Opr r31_oop_opr; + + static LIR_Opr t0_opr; + static LIR_Opr t1_opr; + static LIR_Opr t0_long_opr; + static LIR_Opr t1_long_opr; + + static LIR_Opr r10_metadata_opr; + static LIR_Opr r11_metadata_opr; + static LIR_Opr r12_metadata_opr; + static LIR_Opr r13_metadata_opr; + static LIR_Opr r14_metadata_opr; + static LIR_Opr r15_metadata_opr; + + static LIR_Opr long10_opr; + static LIR_Opr long11_opr; + static LIR_Opr fpu10_float_opr; + static LIR_Opr fpu10_double_opr; + + static LIR_Opr as_long_opr(Register r) { + return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); + } + static LIR_Opr as_pointer_opr(Register r) { + return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); + } + + // VMReg name for spilled physical FPU stack slot n + static VMReg fpu_regname(int n); + + static bool is_caller_save_register(LIR_Opr opr) { return true; } + static bool is_caller_save_register(Register r) { return true; } + + static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; } + static int last_cpu_reg() { return pd_last_cpu_reg; } + +#endif // CPU_RISCV_C1_FRAMEMAP_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c1c13dc29004ebcdbb88329daa52e2efcc534cb --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" + +#ifndef PRODUCT +#define COMMENT(x) do { __ block_comment(x); } while (0) +#else +#define COMMENT(x) +#endif + +#define __ _masm-> + +void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr illegal, + LIR_Opr result, CodeEmitInfo* info) { + // opcode check + assert((code == lir_idiv) || (code == lir_irem), "opcode must be idiv or irem"); + bool is_irem = (code == lir_irem); + // opreand check + assert(left->is_single_cpu(), "left must be a register"); + assert(right->is_single_cpu() || right->is_constant(), "right must be a register or constant"); + assert(result->is_single_cpu(), "result must be a register"); + Register lreg = left->as_register(); + Register dreg = result->as_register(); + + // power-of-2 constant check and codegen + if (right->is_constant()) { + int c = right->as_constant_ptr()->as_jint(); + assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); + if (is_irem) { + if (c == 1) { + // move 0 to dreg if divisor is 1 + __ mv(dreg, zr); + } else { + unsigned int shift = exact_log2(c); + __ sraiw(t0, lreg, 0x1f); + __ srliw(t0, t0, BitsPerInt - shift); + __ addw(t1, lreg, t0); + if (is_imm_in_range(c - 1, 12, 0)) { + __ andi(t1, t1, c - 1); + } else { + __ zero_extend(t1, t1, shift); + } + __ subw(dreg, t1, t0); + } + } else { + if (c == 1) { + // move lreg to dreg if divisor is 1 + __ mv(dreg, lreg); + } else { + unsigned int shift = exact_log2(c); + __ sraiw(t0, lreg, 0x1f); + if (is_imm_in_range(c - 1, 12, 0)) { + __ andi(t0, t0, c - 1); + } else { + __ zero_extend(t0, t0, shift); + } + __ addw(dreg, t0, lreg); + __ sraiw(dreg, dreg, shift); + } + } + } else { + Register rreg = right->as_register(); + __ corrected_idivl(dreg, lreg, rreg, is_irem); + } +} + +void LIR_Assembler::arith_op_single_cpu_right_constant(LIR_Code code, LIR_Opr left, LIR_Opr right, + Register lreg, Register dreg) { + // cpu register - constant + jlong c; + + switch (right->type()) { + case T_LONG: + c = right->as_constant_ptr()->as_jlong(); break; + case T_INT: // fall through + case T_ADDRESS: + c = right->as_constant_ptr()->as_jint(); break; + default: + ShouldNotReachHere(); + c = 0; // unreachable + } + + assert(code == lir_add || code == lir_sub, "mismatched arithmetic op"); + if (c == 0 && dreg == lreg) { + COMMENT("effective nop elided"); + return; + } + switch (left->type()) { + case T_INT: + switch (code) { + case lir_add: __ addw(dreg, lreg, c); break; + case lir_sub: __ subw(dreg, lreg, c); break; + default: ShouldNotReachHere(); + } + break; + case T_OBJECT: // fall through + case T_ADDRESS: + switch (code) { + case lir_add: __ add(dreg, lreg, c); break; + case lir_sub: __ sub(dreg, lreg, c); break; + default: ShouldNotReachHere(); + } + break; + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::arith_op_single_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { + Register lreg = left->as_register(); + Register dreg = as_reg(dest); + + if (right->is_single_cpu()) { + // cpu register - cpu register + assert(left->type() == T_INT && right->type() == T_INT && dest->type() == T_INT, "should be"); + Register rreg = right->as_register(); + switch (code) { + case lir_add: __ addw(dest->as_register(), lreg, rreg); break; + case lir_sub: __ subw(dest->as_register(), lreg, rreg); break; + case lir_mul: __ mulw(dest->as_register(), lreg, rreg); break; + default: ShouldNotReachHere(); + } + } else if (right->is_double_cpu()) { + Register rreg = right->as_register_lo(); + // sigle_cpu + double_cpu; can happen with obj_long + assert(code == lir_add || code == lir_sub, "mismatched arithmetic op"); + switch (code) { + case lir_add: __ add(dreg, lreg, rreg); break; + case lir_sub: __ sub(dreg, lreg, rreg); break; + default: ShouldNotReachHere(); + } + } else if (right->is_constant()) { + arith_op_single_cpu_right_constant(code, left, right, lreg, dreg); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { + Register lreg_lo = left->as_register_lo(); + + if (right->is_double_cpu()) { + // cpu register - cpu register + Register rreg_lo = right->as_register_lo(); + switch (code) { + case lir_add: __ add(dest->as_register_lo(), lreg_lo, rreg_lo); break; + case lir_sub: __ sub(dest->as_register_lo(), lreg_lo, rreg_lo); break; + case lir_mul: __ mul(dest->as_register_lo(), lreg_lo, rreg_lo); break; + case lir_div: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo, false); break; + case lir_rem: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo, true); break; + default: + ShouldNotReachHere(); + } + } else if (right->is_constant()) { + jlong c = right->as_constant_ptr()->as_jlong(); + Register dreg = as_reg(dest); + switch (code) { + case lir_add: // fall through + case lir_sub: + if (c == 0 && dreg == lreg_lo) { + COMMENT("effective nop elided"); + return; + } + code == lir_add ? __ add(dreg, lreg_lo, c) : __ sub(dreg, lreg_lo, c); + break; + case lir_div: + assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); + if (c == 1) { + // move lreg_lo to dreg if divisor is 1 + __ mv(dreg, lreg_lo); + } else { + unsigned int shift = exact_log2_long(c); + // use t0 as intermediate result register + __ srai(t0, lreg_lo, 0x3f); + if (is_imm_in_range(c - 1, 12, 0)) { + __ andi(t0, t0, c - 1); + } else { + __ zero_extend(t0, t0, shift); + } + __ add(dreg, t0, lreg_lo); + __ srai(dreg, dreg, shift); + } + break; + case lir_rem: + assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); + if (c == 1) { + // move 0 to dreg if divisor is 1 + __ mv(dreg, zr); + } else { + unsigned int shift = exact_log2_long(c); + __ srai(t0, lreg_lo, 0x3f); + __ srli(t0, t0, BitsPerLong - shift); + __ add(t1, lreg_lo, t0); + if (is_imm_in_range(c - 1, 12, 0)) { + __ andi(t1, t1, c - 1); + } else { + __ zero_extend(t1, t1, shift); + } + __ sub(dreg, t1, t0); + } + break; + default: + ShouldNotReachHere(); + } + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::arith_op_single_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { + assert(right->is_single_fpu(), "right hand side of float arithmetics needs to be float register"); + switch (code) { + case lir_add: __ fadd_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + case lir_sub: __ fsub_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + case lir_mul: __ fmul_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + case lir_div: __ fdiv_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::arith_op_double_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { + if (right->is_double_fpu()) { + // fpu register - fpu register + switch (code) { + case lir_add: __ fadd_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + case lir_sub: __ fsub_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + case lir_mul: __ fmul_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + case lir_div: __ fdiv_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + default: + ShouldNotReachHere(); + } + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, + CodeEmitInfo* info, bool pop_fpu_stack) { + assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); + + if (left->is_single_cpu()) { + arith_op_single_cpu(code, left, right, dest); + } else if (left->is_double_cpu()) { + arith_op_double_cpu(code, left, right, dest); + } else if (left->is_single_fpu()) { + arith_op_single_fpu(code, left, right, dest); + } else if (left->is_double_fpu()) { + arith_op_double_fpu(code, left, right, dest); + } else { + ShouldNotReachHere(); + } +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ab0a9963fc1134cbcca21ae594a9d6e85af66917 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_LIRASSEMBLER_ARITH_RISCV_HPP +#define CPU_RISCV_C1_LIRASSEMBLER_ARITH_RISCV_HPP + + // arith_op sub functions + void arith_op_single_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest); + void arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest); + void arith_op_single_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest); + void arith_op_double_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest); + void arith_op_single_cpu_right_constant(LIR_Code code, LIR_Opr left, LIR_Opr right, Register lreg, Register dreg); + void arithmetic_idiv(LIR_Op3* op, bool is_irem); + +#endif // CPU_RISCV_C1_LIRASSEMBLER_ARITH_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7f53e395f3ea696b32ef77eb609675f25b62e58 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "ci/ciArrayKlass.hpp" +#include "oops/objArrayKlass.hpp" +#include "runtime/stubRoutines.hpp" + +#define __ _masm-> + + +void LIR_Assembler::generic_arraycopy(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, CodeStub *stub) { + assert(src == x11 && src_pos == x12, "mismatch in calling convention"); + // Save the arguments in case the generic arraycopy fails and we + // have to fall back to the JNI stub + arraycopy_store_args(src, src_pos, length, dst, dst_pos); + + address copyfunc_addr = StubRoutines::generic_arraycopy(); + assert(copyfunc_addr != NULL, "generic arraycopy stub required"); + + // The arguments are in java calling convention so we shift them + // to C convention + assert_different_registers(c_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4); + __ mv(c_rarg0, j_rarg0); + assert_different_registers(c_rarg1, j_rarg2, j_rarg3, j_rarg4); + __ mv(c_rarg1, j_rarg1); + assert_different_registers(c_rarg2, j_rarg3, j_rarg4); + __ mv(c_rarg2, j_rarg2); + assert_different_registers(c_rarg3, j_rarg4); + __ mv(c_rarg3, j_rarg3); + __ mv(c_rarg4, j_rarg4); +#ifndef PRODUCT + if (PrintC1Statistics) { + __ add_memory_int32(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt), 1); + } +#endif + __ far_call(RuntimeAddress(copyfunc_addr)); + __ beqz(x10, *stub->continuation()); + // Reload values from the stack so they are where the stub + // expects them. + arraycopy_load_args(src, src_pos, length, dst, dst_pos); + + // x10 is -1^K where K == partial copied count + __ xori(t0, x10, -1); + // adjust length down and src/end pos up by partial copied count + __ subw(length, length, t0); + __ addw(src_pos, src_pos, t0); + __ addw(dst_pos, dst_pos, t0); + __ j(*stub->entry()); + + __ bind(*stub->continuation()); +} + +void LIR_Assembler::arraycopy_simple_check(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, int flags) { + // test for NULL + if (flags & LIR_OpArrayCopy::src_null_check) { + __ beqz(src, *stub->entry(), /* is_far */ true); + } + if (flags & LIR_OpArrayCopy::dst_null_check) { + __ beqz(dst, *stub->entry(), /* is_far */ true); + } + + // If the compiler was not able to prove that exact type of the source or the destination + // of the arraycopy is an array type, check at runtime if the source or the destination is + // an instance type. + if (flags & LIR_OpArrayCopy::type_check) { + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) { + __ load_klass(tmp, dst); + __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset()))); + __ li(t1, Klass::_lh_neutral_value); + __ bge(t0, t1, *stub->entry(), /* is_far */ true); + } + + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) { + __ load_klass(tmp, src); + __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset()))); + __ li(t1, Klass::_lh_neutral_value); + __ bge(t0, t1, *stub->entry(), /* is_far */ true); + } + } + + // check if negative + if (flags & LIR_OpArrayCopy::src_pos_positive_check) { + __ bltz(src_pos, *stub->entry(), /* is_far */ true); + } + if (flags & LIR_OpArrayCopy::dst_pos_positive_check) { + __ bltz(dst_pos, *stub->entry(), /* is_far */ true); + } + if (flags & LIR_OpArrayCopy::length_positive_check) { + __ bltz(length, *stub->entry(), /* is_far */ true); + } + + if (flags & LIR_OpArrayCopy::src_range_check) { + __ addw(tmp, src_pos, length); + __ lwu(t0, Address(src, arrayOopDesc::length_offset_in_bytes())); + __ bgtu(tmp, t0, *stub->entry(), /* is_far */ true); + } + if (flags & LIR_OpArrayCopy::dst_range_check) { + __ addw(tmp, dst_pos, length); + __ lwu(t0, Address(dst, arrayOopDesc::length_offset_in_bytes())); + __ bgtu(tmp, t0, *stub->entry(), /* is_far */ true); + } +} + +void LIR_Assembler::arraycopy_checkcast(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, BasicType basic_type, + address copyfunc_addr, int flags) { + // src is not a sub class of dst so we have to do a + // per-element check. + int mask = LIR_OpArrayCopy::src_objarray | LIR_OpArrayCopy::dst_objarray; + if ((flags & mask) != mask) { + // Check that at least both of them object arrays. + assert(flags & mask, "one of the two should be known to be an object array"); + + if (!(flags & LIR_OpArrayCopy::src_objarray)) { + __ load_klass(tmp, src); + } else if (!(flags & LIR_OpArrayCopy::dst_objarray)) { + __ load_klass(tmp, dst); + } + int lh_offset = in_bytes(Klass::layout_helper_offset()); + Address klass_lh_addr(tmp, lh_offset); + jint objArray_lh = Klass::array_layout_helper(T_OBJECT); + __ lw(t0, klass_lh_addr); + __ mvw(t1, objArray_lh); + __ bne(t0, t1, *stub->entry(), /* is_far */ true); + } + + // Spill because stubs can use any register they like and it's + // easier to restore just those that we care about. + arraycopy_store_args(src, src_pos, length, dst, dst_pos); + arraycopy_checkcast_prepare_params(src, src_pos, length, dst, dst_pos, basic_type); + __ far_call(RuntimeAddress(copyfunc_addr)); + +#ifndef PRODUCT + if (PrintC1Statistics) { + Label failed; + __ bnez(x10, failed); + __ add_memory_int32(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_cnt), 1); + __ bind(failed); + } +#endif + + __ beqz(x10, *stub->continuation()); + +#ifndef PRODUCT + if (PrintC1Statistics) { + __ add_memory_int32(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_attempt_cnt), 1); + } +#endif + assert_different_registers(dst, dst_pos, length, src_pos, src, x10, t0); + + // Restore previously spilled arguments + arraycopy_load_args(src, src_pos, length, dst, dst_pos); + + // return value is -1^K where K is partial copied count + __ xori(t0, x10, -1); + // adjust length down and src/end pos up by partial copied count + __ subw(length, length, t0); + __ addw(src_pos, src_pos, t0); + __ addw(dst_pos, dst_pos, t0); +} + +void LIR_Assembler::arraycopy_type_check(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, BasicType basic_type, int flags) { + // We don't know the array types are compatible + if (basic_type != T_OBJECT) { + // Simple test for basic type arrays + if (UseCompressedClassPointers) { + __ lwu(tmp, Address(src, oopDesc::klass_offset_in_bytes())); + __ lwu(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } else { + __ ld(tmp, Address(src, oopDesc::klass_offset_in_bytes())); + __ ld(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } + __ bne(tmp, t0, *stub->entry(), /* is_far */ true); + } else { + // For object arrays, if src is a sub class of dst then we can + // safely do the copy. + Label cont, slow; + +#define PUSH(r1, r2) \ + __ addi(sp, sp, -2 * wordSize); \ + __ sd(r1, Address(sp, 1 * wordSize)); \ + __ sd(r2, Address(sp, 0)); + +#define POP(r1, r2) \ + __ ld(r1, Address(sp, 1 * wordSize)); \ + __ ld(r2, Address(sp, 0)); \ + __ addi(sp, sp, 2 * wordSize); + + PUSH(src, dst); + __ load_klass(src, src); + __ load_klass(dst, dst); + __ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, NULL); + + PUSH(src, dst); + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + POP(src, dst); + __ bnez(dst, cont); + + __ bind(slow); + POP(src, dst); + + address copyfunc_addr = StubRoutines::checkcast_arraycopy(); + if (copyfunc_addr != NULL) { // use stub if available + arraycopy_checkcast(src, src_pos, length, dst, dst_pos, tmp, stub, basic_type, copyfunc_addr, flags); + } + + __ j(*stub->entry()); + __ bind(cont); + POP(src, dst); + } +} + +void LIR_Assembler::arraycopy_assert(Register src, Register dst, Register tmp, ciArrayKlass *default_type, int flags) { + assert(default_type != NULL, "NULL default_type!"); + BasicType basic_type = default_type->element_type()->basic_type(); + + if (basic_type == T_ARRAY) { basic_type = T_OBJECT; } + if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) { + // Sanity check the known type with the incoming class. For the + // primitive case the types must match exactly with src.klass and + // dst.klass each exactly matching the default type. For the + // object array case, if no type check is needed then either the + // dst type is exactly the expected type and the src type is a + // subtype which we can't check or src is the same array as dst + // but not necessarily exactly of type default_type. + Label known_ok, halt; + __ mov_metadata(tmp, default_type->constant_encoding()); + if (UseCompressedClassPointers) { + __ encode_klass_not_null(tmp); + } + + if (basic_type != T_OBJECT) { + if (UseCompressedClassPointers) { + __ lwu(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } else { + __ ld(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } + __ bne(tmp, t0, halt); + if (UseCompressedClassPointers) { + __ lwu(t0, Address(src, oopDesc::klass_offset_in_bytes())); + } else { + __ ld(t0, Address(src, oopDesc::klass_offset_in_bytes())); + } + __ beq(tmp, t0, known_ok); + } else { + if (UseCompressedClassPointers) { + __ lwu(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } else { + __ ld(t0, Address(dst, oopDesc::klass_offset_in_bytes())); + } + __ beq(tmp, t0, known_ok); + __ beq(src, dst, known_ok); + } + __ bind(halt); + __ stop("incorrect type information in arraycopy"); + __ bind(known_ok); + } +} + +void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { + ciArrayKlass *default_type = op->expected_type(); + Register src = op->src()->as_register(); + Register dst = op->dst()->as_register(); + Register src_pos = op->src_pos()->as_register(); + Register dst_pos = op->dst_pos()->as_register(); + Register length = op->length()->as_register(); + Register tmp = op->tmp()->as_register(); + + CodeStub* stub = op->stub(); + int flags = op->flags(); + BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; + if (is_reference_type(basic_type)) { basic_type = T_OBJECT; } + + // if we don't know anything, just go through the generic arraycopy + if (default_type == NULL) { + generic_arraycopy(src, src_pos, length, dst, dst_pos, stub); + return; + } + + assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), + "must be true at this point"); + + arraycopy_simple_check(src, src_pos, length, dst, dst_pos, tmp, stub, flags); + + if (flags & LIR_OpArrayCopy::type_check) { + arraycopy_type_check(src, src_pos, length, dst, dst_pos, tmp, stub, basic_type, flags); + } + +#ifdef ASSERT + arraycopy_assert(src, dst, tmp, default_type, flags); +#endif + +#ifndef PRODUCT + if (PrintC1Statistics) { + __ add_memory_int32(ExternalAddress(Runtime1::arraycopy_count_address(basic_type)), 1); + } +#endif + arraycopy_prepare_params(src, src_pos, length, dst, dst_pos, basic_type); + + bool disjoint = (flags & LIR_OpArrayCopy::overlapping) == 0; + bool aligned = (flags & LIR_OpArrayCopy::unaligned) == 0; + const char *name = NULL; + address entry = StubRoutines::select_arraycopy_function(basic_type, aligned, disjoint, name, false); + + CodeBlob *cb = CodeCache::find_blob(entry); + if (cb != NULL) { + __ far_call(RuntimeAddress(entry)); + } else { + const int args_num = 3; + __ call_VM_leaf(entry, args_num); + } + + __ bind(*stub->continuation()); +} + + +void LIR_Assembler::arraycopy_prepare_params(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, BasicType basic_type) { + int scale = array_element_size(basic_type); + __ shadd(c_rarg0, src_pos, src, t0, scale); + __ add(c_rarg0, c_rarg0, arrayOopDesc::base_offset_in_bytes(basic_type)); + assert_different_registers(c_rarg0, dst, dst_pos, length); + __ shadd(c_rarg1, dst_pos, dst, t0, scale); + __ add(c_rarg1, c_rarg1, arrayOopDesc::base_offset_in_bytes(basic_type)); + assert_different_registers(c_rarg1, dst, length); + __ mv(c_rarg2, length); + assert_different_registers(c_rarg2, dst); +} + +void LIR_Assembler::arraycopy_checkcast_prepare_params(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, BasicType basic_type) { + arraycopy_prepare_params(src, src_pos, length, dst, dst_pos, basic_type); + __ load_klass(c_rarg4, dst); + __ ld(c_rarg4, Address(c_rarg4, ObjArrayKlass::element_klass_offset())); + __ lwu(c_rarg3, Address(c_rarg4, Klass::super_check_offset_offset())); +} + +void LIR_Assembler::arraycopy_store_args(Register src, Register src_pos, Register length, + Register dst, Register dst_pos) { + __ sd(dst_pos, Address(sp, 0)); // 0: dst_pos sp offset + __ sd(dst, Address(sp, 1 * BytesPerWord)); // 1: dst sp offset + __ sd(length, Address(sp, 2 * BytesPerWord)); // 2: length sp offset + __ sd(src_pos, Address(sp, 3 * BytesPerWord)); // 3: src_pos sp offset + __ sd(src, Address(sp, 4 * BytesPerWord)); // 4: src sp offset +} + +void LIR_Assembler::arraycopy_load_args(Register src, Register src_pos, Register length, + Register dst, Register dst_pos) { + __ ld(dst_pos, Address(sp, 0)); // 0: dst_pos sp offset + __ ld(dst, Address(sp, 1 * BytesPerWord)); // 1: dst sp offset + __ ld(length, Address(sp, 2 * BytesPerWord)); // 2: length sp offset + __ ld(src_pos, Address(sp, 3 * BytesPerWord)); // 3: src_pos sp offset + __ ld(src, Address(sp, 4 * BytesPerWord)); // 4: src sp offset +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..06a0f248ca690168d0113d66939462dabefe3562 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_LIRASSEMBLER_ARRAYCOPY_RISCV_HPP +#define CPU_RISCV_C1_LIRASSEMBLER_ARRAYCOPY_RISCV_HPP + + // arraycopy sub functions + void generic_arraycopy(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, CodeStub *stub); + void arraycopy_simple_check(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, int flags); + void arraycopy_checkcast(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, BasicType basic_type, + address copyfunc_addr, int flags); + void arraycopy_type_check(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, Register tmp, + CodeStub *stub, BasicType basic_type, int flags); + void arraycopy_assert(Register src, Register dst, Register tmp, ciArrayKlass *default_type, int flags); + void arraycopy_prepare_params(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, BasicType basic_type); + void arraycopy_checkcast_prepare_params(Register src, Register src_pos, Register length, + Register dst, Register dst_pos, BasicType basic_type); + void arraycopy_store_args(Register src, Register src_pos, Register length, + Register dst, Register dst_pos); + void arraycopy_load_args(Register src, Register src_pos, Register length, + Register dst, Register dst_pos); + +#endif // CPU_RISCV_C1_LIRASSEMBLER_ARRAYCOPY_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..742c2126e60b20d8ab394f29f81be8ed5b383be3 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -0,0 +1,2267 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_CodeStubs.hpp" +#include "c1/c1_Compilation.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "c1/c1_Runtime1.hpp" +#include "c1/c1_ValueStack.hpp" +#include "ci/ciArrayKlass.hpp" +#include "ci/ciInstance.hpp" +#include "code/compiledIC.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/objArrayKlass.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + +#ifndef PRODUCT +#define COMMENT(x) do { __ block_comment(x); } while (0) +#else +#define COMMENT(x) +#endif + +NEEDS_CLEANUP // remove this definitions ? +const Register IC_Klass = t1; // where the IC klass is cached +const Register SYNC_header = x10; // synchronization header +const Register SHIFT_count = x10; // where count for shift operations must be + +#define __ _masm-> + +static void select_different_registers(Register preserve, + Register extra, + Register &tmp1, + Register &tmp2) { + if (tmp1 == preserve) { + assert_different_registers(tmp1, tmp2, extra); + tmp1 = extra; + } else if (tmp2 == preserve) { + assert_different_registers(tmp1, tmp2, extra); + tmp2 = extra; + } + assert_different_registers(preserve, tmp1, tmp2); +} + +static void select_different_registers(Register preserve, + Register extra, + Register &tmp1, + Register &tmp2, + Register &tmp3) { + if (tmp1 == preserve) { + assert_different_registers(tmp1, tmp2, tmp3, extra); + tmp1 = extra; + } else if (tmp2 == preserve) { + assert_different_registers(tmp1, tmp2, tmp3, extra); + tmp2 = extra; + } else if (tmp3 == preserve) { + assert_different_registers(tmp1, tmp2, tmp3, extra); + tmp3 = extra; + } + assert_different_registers(preserve, tmp1, tmp2, tmp3); +} + +bool LIR_Assembler::is_small_constant(LIR_Opr opr) { Unimplemented(); return false; } + +void LIR_Assembler::clinit_barrier(ciMethod* method) { + assert(VM_Version::supports_fast_class_init_checks(), "sanity"); + assert(!method->holder()->is_not_initialized(), "initialization should have been started"); + + Label L_skip_barrier; + + __ mov_metadata(t1, method->holder()->constant_encoding()); + __ clinit_barrier(t1, t0, &L_skip_barrier /* L_fast_path */); + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + __ bind(L_skip_barrier); +} + +LIR_Opr LIR_Assembler::receiverOpr() { + return FrameMap::receiver_opr; +} + +LIR_Opr LIR_Assembler::osrBufferPointer() { + return FrameMap::as_pointer_opr(receiverOpr()->as_register()); +} + +void LIR_Assembler::breakpoint() { Unimplemented(); } + +void LIR_Assembler::push(LIR_Opr opr) { Unimplemented(); } + +void LIR_Assembler::pop(LIR_Opr opr) { Unimplemented(); } + +static jlong as_long(LIR_Opr data) { + jlong result; + switch (data->type()) { + case T_INT: + result = (data->as_jint()); + break; + case T_LONG: + result = (data->as_jlong()); + break; + default: + ShouldNotReachHere(); + result = 0; // unreachable + } + return result; +} + +Address LIR_Assembler::as_Address(LIR_Address* addr, Register tmp) { + if (addr->base()->is_illegal()) { + assert(addr->index()->is_illegal(), "must be illegal too"); + __ movptr(tmp, addr->disp()); + return Address(tmp, 0); + } + + Register base = addr->base()->as_pointer_register(); + LIR_Opr index_opr = addr->index(); + + if (index_opr->is_illegal()) { + return Address(base, addr->disp()); + } + + int scale = addr->scale(); + if (index_opr->is_cpu_register()) { + Register index; + if (index_opr->is_single_cpu()) { + index = index_opr->as_register(); + } else { + index = index_opr->as_register_lo(); + } + if (scale != 0) { + __ shadd(tmp, index, base, tmp, scale); + } else { + __ add(tmp, base, index); + } + return Address(tmp, addr->disp()); + } else if (index_opr->is_constant()) { + intptr_t addr_offset = (((intptr_t)index_opr->as_constant_ptr()->as_jint()) << scale) + addr->disp(); + return Address(base, addr_offset); + } + + Unimplemented(); + return Address(); +} + +Address LIR_Assembler::as_Address_hi(LIR_Address* addr) { + ShouldNotReachHere(); + return Address(); +} + +Address LIR_Assembler::as_Address(LIR_Address* addr) { + return as_Address(addr, t0); +} + +Address LIR_Assembler::as_Address_lo(LIR_Address* addr) { + return as_Address(addr); +} + +// Ensure a valid Address (base + offset) to a stack-slot. If stack access is +// not encodable as a base + (immediate) offset, generate an explicit address +// calculation to hold the address in t0. +Address LIR_Assembler::stack_slot_address(int index, uint size, int adjust) { + precond(size == 4 || size == 8); + Address addr = frame_map()->address_for_slot(index, adjust); + precond(addr.getMode() == Address::base_plus_offset); + precond(addr.base() == sp); + precond(addr.offset() > 0); + uint mask = size - 1; + assert((addr.offset() & mask) == 0, "scaled offsets only"); + + return addr; +} + +void LIR_Assembler::osr_entry() { + offsets()->set_value(CodeOffsets::OSR_Entry, code_offset()); + BlockBegin* osr_entry = compilation()->hir()->osr_entry(); + guarantee(osr_entry != NULL, "NULL osr_entry!"); + ValueStack* entry_state = osr_entry->state(); + int number_of_locks = entry_state->locks_size(); + + // we jump here if osr happens with the interpreter + // state set up to continue at the beginning of the + // loop that triggered osr - in particular, we have + // the following registers setup: + // + // x12: osr buffer + // + + //build frame + ciMethod* m = compilation()->method(); + __ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); + + // OSR buffer is + // + // locals[nlocals-1..0] + // monitors[0..number_of_locks] + // + // locals is a direct copy of the interpreter frame so in the osr buffer + // so first slot in the local array is the last local from the interpreter + // and last slot is local[0] (receiver) from the interpreter + // + // Similarly with locks. The first lock slot in the osr buffer is the nth lock + // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock + // in the interpreter frame (the method lock if a sync method) + + // Initialize monitors in the compiled activation. + // x12: pointer to osr buffer + // All other registers are dead at this point and the locals will be + // copied into place by code emitted in the IR. + + Register OSR_buf = osrBufferPointer()->as_pointer_register(); + { + assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); + int monitor_offset = BytesPerWord * method()->max_locals() + + (2 * BytesPerWord) * (number_of_locks - 1); + // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in + // the OSR buffer using 2 word entries: first the lock and then + // the oop. + for (int i = 0; i < number_of_locks; i++) { + int slot_offset = monitor_offset - ((i * 2) * BytesPerWord); +#ifdef ASSERT + // verify the interpreter's monitor has a non-null object + { + Label L; + __ ld(t0, Address(OSR_buf, slot_offset + 1 * BytesPerWord)); + __ bnez(t0, L); + __ stop("locked object is NULL"); + __ bind(L); + } +#endif // ASSERT + __ ld(x9, Address(OSR_buf, slot_offset + 0)); + __ sd(x9, frame_map()->address_for_monitor_lock(i)); + __ ld(x9, Address(OSR_buf, slot_offset + 1 * BytesPerWord)); + __ sd(x9, frame_map()->address_for_monitor_object(i)); + } + } +} + +// inline cache check; done before the frame is built. +int LIR_Assembler::check_icache() { + Register receiver = FrameMap::receiver_opr->as_register(); + Register ic_klass = IC_Klass; + int start_offset = __ offset(); + Label dont; + __ inline_cache_check(receiver, ic_klass, dont); + + // if icache check fails, then jump to runtime routine + // Note: RECEIVER must still contain the receiver! + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + + // We align the verified entry point unless the method body + // (including its inline cache check) will fit in a single 64-byte + // icache line. + if (!method()->is_accessor() || __ offset() - start_offset > 4 * 4) { + // force alignment after the cache check. + __ align(CodeEntryAlignment); + } + + __ bind(dont); + return start_offset; +} + +void LIR_Assembler::jobject2reg(jobject o, Register reg) { + if (o == NULL) { + __ mv(reg, zr); + } else { + __ movoop(reg, o, /* immediate */ true); + } +} + +void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo *info) { + deoptimize_trap(info); +} + +// This specifies the rsp decrement needed to build the frame +int LIR_Assembler::initial_frame_size_in_bytes() const { + // if rounding, must let FrameMap know! + + return in_bytes(frame_map()->framesize_in_bytes()); +} + +int LIR_Assembler::emit_exception_handler() { + // if the last instruction is a call (typically to do a throw which + // is coming at the end after block reordering) the return address + // must still point into the code area in order to avoid assertion + // failures when searching for the corresponding bci ==> add a nop + // (was bug 5/14/1999 -gri) + __ nop(); + + // generate code for exception handler + address handler_base = __ start_a_stub(exception_handler_size()); + if (handler_base == NULL) { + // not enough space left for the handler + bailout("exception handler overflow"); + return -1; + } + + int offset = code_offset(); + + // the exception oop and pc are in x10, and x13 + // no other registers need to be preserved, so invalidate them + __ invalidate_registers(false, true, true, false, true, true); + + // check that there is really an exception + __ verify_not_null_oop(x10); + + // search an exception handler (x10: exception oop, x13: throwing pc) + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id))); + __ should_not_reach_here(); + guarantee(code_offset() - offset <= exception_handler_size(), "overflow"); + __ end_a_stub(); + + return offset; +} + +// Emit the code to remove the frame from the stack in the exception +// unwind path. +int LIR_Assembler::emit_unwind_handler() { +#ifndef PRODUCT + if (CommentedAssembly) { + _masm->block_comment("Unwind handler"); + } +#endif // PRODUCT + + int offset = code_offset(); + + // Fetch the exception from TLS and clear out exception related thread state + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); + + __ bind(_unwind_handler_entry); + __ verify_not_null_oop(x10); + if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { + __ mv(x9, x10); // Perserve the exception + } + + // Preform needed unlocking + MonitorExitStub* stub = NULL; + if (method()->is_synchronized()) { + monitor_address(0, FrameMap::r10_opr); + stub = new MonitorExitStub(FrameMap::r10_opr, true, 0); + if (UseHeavyMonitors) { + __ j(*stub->entry()); + } else { + __ unlock_object(x15, x14, x10, *stub->entry()); + } + __ bind(*stub->continuation()); + } + + if (compilation()->env()->dtrace_method_probes()) { + __ mv(c_rarg0, xthread); + __ mov_metadata(c_rarg1, method()->constant_encoding()); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), c_rarg0, c_rarg1); + } + + if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { + __ mv(x10, x9); // Restore the exception + } + + // remove the activation and dispatch to the unwind handler + __ block_comment("remove_frame and dispatch to the unwind handler"); + __ remove_frame(initial_frame_size_in_bytes()); + __ far_jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); + + // Emit the slow path assembly + if (stub != NULL) { + stub->emit_code(this); + } + + return offset; +} + +int LIR_Assembler::emit_deopt_handler() { + // if the last instruciton is a call (typically to do a throw which + // is coming at the end after block reordering) the return address + // must still point into the code area in order to avoid assertion + // failures when searching for the corresponding bck => add a nop + // (was bug 5/14/1999 - gri) + __ nop(); + + // generate code for exception handler + address handler_base = __ start_a_stub(deopt_handler_size()); + if (handler_base == NULL) { + // not enough space left for the handler + bailout("deopt handler overflow"); + return -1; + } + + int offset = code_offset(); + + __ auipc(ra, 0); + __ far_jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); + guarantee(code_offset() - offset <= deopt_handler_size(), "overflow"); + __ end_a_stub(); + + return offset; +} + +void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { + assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == x10, "word returns are in x10"); + + // Pop the stack before the safepoint code + __ remove_frame(initial_frame_size_in_bytes()); + + if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) { + __ reserved_stack_check(); + } + + code_stub->set_safepoint_offset(__ offset()); + __ relocate(relocInfo::poll_return_type); + __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ ret(); +} + +int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { + guarantee(info != NULL, "Shouldn't be NULL"); + __ get_polling_page(t0, relocInfo::poll_type); + add_debug_info_for_branch(info); // This isn't just debug info: + // it's the oop map + __ read_polling_page(t0, 0, relocInfo::poll_type); + return __ offset(); +} + +void LIR_Assembler::move_regs(Register from_reg, Register to_reg) { + __ mv(to_reg, from_reg); +} + +void LIR_Assembler::swap_reg(Register a, Register b) { Unimplemented(); } + +void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { + assert(src->is_constant(), "should not call otherwise"); + assert(dest->is_register(), "should not call otherwise"); + LIR_Const* c = src->as_constant_ptr(); + address const_addr = NULL; + + switch (c->type()) { + case T_INT: + assert(patch_code == lir_patch_none, "no patching handled here"); + __ mvw(dest->as_register(), c->as_jint()); + break; + + case T_ADDRESS: + assert(patch_code == lir_patch_none, "no patching handled here"); + __ mv(dest->as_register(), c->as_jint()); + break; + + case T_LONG: + assert(patch_code == lir_patch_none, "no patching handled here"); + __ mv(dest->as_register_lo(), (intptr_t)c->as_jlong()); + break; + + case T_OBJECT: + case T_ARRAY: + if (patch_code == lir_patch_none) { + jobject2reg(c->as_jobject(), dest->as_register()); + } else { + jobject2reg_with_patching(dest->as_register(), info); + } + break; + + case T_METADATA: + if (patch_code != lir_patch_none) { + klass2reg_with_patching(dest->as_register(), info); + } else { + __ mov_metadata(dest->as_register(), c->as_metadata()); + } + break; + + case T_FLOAT: + const_addr = float_constant(c->as_jfloat()); + assert(const_addr != NULL, "must create float constant in the constant table"); + __ flw(dest->as_float_reg(), InternalAddress(const_addr)); + break; + + case T_DOUBLE: + const_addr = double_constant(c->as_jdouble()); + assert(const_addr != NULL, "must create double constant in the constant table"); + __ fld(dest->as_double_reg(), InternalAddress(const_addr)); + break; + + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { + assert(src->is_constant(), "should not call otherwise"); + assert(dest->is_stack(), "should not call otherwise"); + LIR_Const* c = src->as_constant_ptr(); + switch (c->type()) { + case T_OBJECT: + if (c->as_jobject() == NULL) { + __ sd(zr, frame_map()->address_for_slot(dest->single_stack_ix())); + } else { + const2reg(src, FrameMap::t1_opr, lir_patch_none, NULL); + reg2stack(FrameMap::t1_opr, dest, c->type(), false); + } + break; + case T_ADDRESS: // fall through + const2reg(src, FrameMap::t1_opr, lir_patch_none, NULL); + reg2stack(FrameMap::t1_opr, dest, c->type(), false); + case T_INT: // fall through + case T_FLOAT: + if (c->as_jint_bits() == 0) { + __ sw(zr, frame_map()->address_for_slot(dest->single_stack_ix())); + } else { + __ mvw(t1, c->as_jint_bits()); + __ sw(t1, frame_map()->address_for_slot(dest->single_stack_ix())); + } + break; + case T_LONG: // fall through + case T_DOUBLE: + if (c->as_jlong_bits() == 0) { + __ sd(zr, frame_map()->address_for_slot(dest->double_stack_ix(), + lo_word_offset_in_bytes)); + } else { + __ mv(t1, (intptr_t)c->as_jlong_bits()); + __ sd(t1, frame_map()->address_for_slot(dest->double_stack_ix(), + lo_word_offset_in_bytes)); + } + break; + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { + assert(src->is_constant(), "should not call otherwise"); + assert(dest->is_address(), "should not call otherwise"); + LIR_Const* c = src->as_constant_ptr(); + LIR_Address* to_addr = dest->as_address_ptr(); + void (Assembler::* insn)(Register Rt, const Address &adr, Register temp); + switch (type) { + case T_ADDRESS: + assert(c->as_jint() == 0, "should be"); + insn = &Assembler::sd; break; + case T_LONG: + assert(c->as_jlong() == 0, "should be"); + insn = &Assembler::sd; break; + case T_DOUBLE: + assert(c->as_jdouble() == 0.0, "should be"); + insn = &Assembler::sd; break; + case T_INT: + assert(c->as_jint() == 0, "should be"); + insn = &Assembler::sw; break; + case T_FLOAT: + assert(c->as_jfloat() == 0.0f, "should be"); + insn = &Assembler::sw; break; + case T_OBJECT: // fall through + case T_ARRAY: + assert(c->as_jobject() == 0, "should be"); + if (UseCompressedOops && !wide) { + insn = &Assembler::sw; + } else { + insn = &Assembler::sd; + } + break; + case T_CHAR: // fall through + case T_SHORT: + assert(c->as_jint() == 0, "should be"); + insn = &Assembler::sh; + break; + case T_BOOLEAN: // fall through + case T_BYTE: + assert(c->as_jint() == 0, "should be"); + insn = &Assembler::sb; break; + default: + ShouldNotReachHere(); + insn = &Assembler::sd; // unreachable + } + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + (_masm->*insn)(zr, as_Address(to_addr), t0); +} + +void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { + assert(src->is_register(), "should not call otherwise"); + assert(dest->is_register(), "should not call otherwise"); + + // move between cpu-registers + if (dest->is_single_cpu()) { + if (src->type() == T_LONG) { + // Can do LONG -> OBJECT + move_regs(src->as_register_lo(), dest->as_register()); + return; + } + assert(src->is_single_cpu(), "must match"); + if (src->type() == T_OBJECT) { + __ verify_oop(src->as_register()); + } + move_regs(src->as_register(), dest->as_register()); + } else if (dest->is_double_cpu()) { + if (is_reference_type(src->type())) { + __ verify_oop(src->as_register()); + move_regs(src->as_register(), dest->as_register_lo()); + return; + } + assert(src->is_double_cpu(), "must match"); + Register f_lo = src->as_register_lo(); + Register f_hi = src->as_register_hi(); + Register t_lo = dest->as_register_lo(); + Register t_hi = dest->as_register_hi(); + assert(f_hi == f_lo, "must be same"); + assert(t_hi == t_lo, "must be same"); + move_regs(f_lo, t_lo); + } else if (dest->is_single_fpu()) { + assert(src->is_single_fpu(), "expect single fpu"); + __ fmv_s(dest->as_float_reg(), src->as_float_reg()); + } else if (dest->is_double_fpu()) { + assert(src->is_double_fpu(), "expect double fpu"); + __ fmv_d(dest->as_double_reg(), src->as_double_reg()); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack) { + precond(src->is_register() && dest->is_stack()); + + uint const c_sz32 = sizeof(uint32_t); + uint const c_sz64 = sizeof(uint64_t); + + assert(src->is_register(), "should not call otherwise"); + assert(dest->is_stack(), "should not call otherwise"); + if (src->is_single_cpu()) { + int index = dest->single_stack_ix(); + if (is_reference_type(type)) { + __ sd(src->as_register(), stack_slot_address(index, c_sz64)); + __ verify_oop(src->as_register()); + } else if (type == T_METADATA || type == T_DOUBLE || type == T_ADDRESS) { + __ sd(src->as_register(), stack_slot_address(index, c_sz64)); + } else { + __ sw(src->as_register(), stack_slot_address(index, c_sz32)); + } + } else if (src->is_double_cpu()) { + int index = dest->double_stack_ix(); + Address dest_addr_LO = stack_slot_address(index, c_sz64, lo_word_offset_in_bytes); + __ sd(src->as_register_lo(), dest_addr_LO); + } else if (src->is_single_fpu()) { + int index = dest->single_stack_ix(); + __ fsw(src->as_float_reg(), stack_slot_address(index, c_sz32)); + } else if (src->is_double_fpu()) { + int index = dest->double_stack_ix(); + __ fsd(src->as_double_reg(), stack_slot_address(index, c_sz64)); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide) { + LIR_Address* to_addr = dest->as_address_ptr(); + // t0 was used as tmp reg in as_Address, so we use t1 as compressed_src + Register compressed_src = t1; + + if (patch_code != lir_patch_none) { + deoptimize_trap(info); + return; + } + + if (is_reference_type(type)) { + __ verify_oop(src->as_register()); + + if (UseCompressedOops && !wide) { + __ encode_heap_oop(compressed_src, src->as_register()); + } else { + compressed_src = src->as_register(); + } + } + + int null_check_here = code_offset(); + + switch (type) { + case T_FLOAT: + __ fsw(src->as_float_reg(), as_Address(to_addr)); + break; + + case T_DOUBLE: + __ fsd(src->as_double_reg(), as_Address(to_addr)); + break; + + case T_ARRAY: // fall through + case T_OBJECT: + if (UseCompressedOops && !wide) { + __ sw(compressed_src, as_Address(to_addr)); + } else { + __ sd(compressed_src, as_Address(to_addr)); + } + break; + case T_METADATA: + // We get here to store a method pointer to the stack to pass to + // a dtrace runtime call. This can't work on 64 bit with + // compressed klass ptrs: T_METADATA can be compressed klass + // ptr or a 64 bit method pointer. + ShouldNotReachHere(); + __ sd(src->as_register(), as_Address(to_addr)); + break; + case T_ADDRESS: + __ sd(src->as_register(), as_Address(to_addr)); + break; + case T_INT: + __ sw(src->as_register(), as_Address(to_addr)); + break; + case T_LONG: + __ sd(src->as_register_lo(), as_Address(to_addr)); + break; + case T_BYTE: // fall through + case T_BOOLEAN: + __ sb(src->as_register(), as_Address(to_addr)); + break; + case T_CHAR: // fall through + case T_SHORT: + __ sh(src->as_register(), as_Address(to_addr)); + break; + default: + ShouldNotReachHere(); + } + + if (info != NULL) { + add_debug_info_for_null_check(null_check_here, info); + } +} + +void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { + precond(src->is_stack() && dest->is_register()); + + uint const c_sz32 = sizeof(uint32_t); + uint const c_sz64 = sizeof(uint64_t); + + if (dest->is_single_cpu()) { + int index = src->single_stack_ix(); + if (type == T_INT) { + __ lw(dest->as_register(), stack_slot_address(index, c_sz32)); + } else if (is_reference_type(type)) { + __ ld(dest->as_register(), stack_slot_address(index, c_sz64)); + __ verify_oop(dest->as_register()); + } else if (type == T_METADATA || type == T_ADDRESS) { + __ ld(dest->as_register(), stack_slot_address(index, c_sz64)); + } else { + __ lwu(dest->as_register(), stack_slot_address(index, c_sz32)); + } + } else if (dest->is_double_cpu()) { + int index = src->double_stack_ix(); + Address src_addr_LO = stack_slot_address(index, c_sz64, lo_word_offset_in_bytes); + __ ld(dest->as_register_lo(), src_addr_LO); + } else if (dest->is_single_fpu()) { + int index = src->single_stack_ix(); + __ flw(dest->as_float_reg(), stack_slot_address(index, c_sz32)); + } else if (dest->is_double_fpu()) { + int index = src->double_stack_ix(); + __ fld(dest->as_double_reg(), stack_slot_address(index, c_sz64)); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) { + deoptimize_trap(info); +} + +void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { + LIR_Opr temp; + if (type == T_LONG || type == T_DOUBLE) { + temp = FrameMap::t1_long_opr; + } else { + temp = FrameMap::t1_opr; + } + + stack2reg(src, temp, src->type()); + reg2stack(temp, dest, dest->type(), false); +} + +void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide) { + assert(src->is_address(), "should not call otherwise"); + assert(dest->is_register(), "should not call otherwise"); + + LIR_Address* addr = src->as_address_ptr(); + LIR_Address* from_addr = src->as_address_ptr(); + + if (addr->base()->type() == T_OBJECT) { + __ verify_oop(addr->base()->as_pointer_register()); + } + + if (patch_code != lir_patch_none) { + deoptimize_trap(info); + return; + } + + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + + int null_check_here = code_offset(); + switch (type) { + case T_FLOAT: + __ flw(dest->as_float_reg(), as_Address(from_addr)); + break; + case T_DOUBLE: + __ fld(dest->as_double_reg(), as_Address(from_addr)); + break; + case T_ARRAY: // fall through + case T_OBJECT: + if (UseCompressedOops && !wide) { + __ lwu(dest->as_register(), as_Address(from_addr)); + } else { + __ ld(dest->as_register(), as_Address(from_addr)); + } + break; + case T_METADATA: + // We get here to store a method pointer to the stack to pass to + // a dtrace runtime call. This can't work on 64 bit with + // compressed klass ptrs: T_METADATA can be a compressed klass + // ptr or a 64 bit method pointer. + ShouldNotReachHere(); + __ ld(dest->as_register(), as_Address(from_addr)); + break; + case T_ADDRESS: + __ ld(dest->as_register(), as_Address(from_addr)); + break; + case T_INT: + __ lw(dest->as_register(), as_Address(from_addr)); + break; + case T_LONG: + __ ld(dest->as_register_lo(), as_Address_lo(from_addr)); + break; + case T_BYTE: + __ lb(dest->as_register(), as_Address(from_addr)); + break; + case T_BOOLEAN: + __ lbu(dest->as_register(), as_Address(from_addr)); + break; + case T_CHAR: + __ lhu(dest->as_register(), as_Address(from_addr)); + break; + case T_SHORT: + __ lh(dest->as_register(), as_Address(from_addr)); + break; + default: + ShouldNotReachHere(); + } + + if (is_reference_type(type)) { + if (UseCompressedOops && !wide) { + __ decode_heap_oop(dest->as_register()); + } + + if (!UseZGC) { + // Load barrier has not yet been applied, so ZGC can't verify the oop here + __ verify_oop(dest->as_register()); + } + } +} + +void LIR_Assembler::emit_op3(LIR_Op3* op) { + switch (op->code()) { + case lir_idiv: // fall through + case lir_irem: + arithmetic_idiv(op->code(), + op->in_opr1(), + op->in_opr2(), + op->in_opr3(), + op->result_opr(), + op->info()); + break; + case lir_fmad: + __ fmadd_d(op->result_opr()->as_double_reg(), + op->in_opr1()->as_double_reg(), + op->in_opr2()->as_double_reg(), + op->in_opr3()->as_double_reg()); + break; + case lir_fmaf: + __ fmadd_s(op->result_opr()->as_float_reg(), + op->in_opr1()->as_float_reg(), + op->in_opr2()->as_float_reg(), + op->in_opr3()->as_float_reg()); + break; + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + Label label; + + emit_branch(condition, cmp_opr1, cmp_opr2, label, /* is_far */ false, + /* is_unordered */ (condition == lir_cond_greaterEqual || condition == lir_cond_greater) ? false : true); + + Label done; + move_op(opr2, result, type, lir_patch_none, NULL, + false, // pop_fpu_stack + false); // wide + __ j(done); + __ bind(label); + move_op(opr1, result, type, lir_patch_none, NULL, + false, // pop_fpu_stack + false); // wide + __ bind(done); +} + +void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { + LIR_Condition condition = op->cond(); + if (condition == lir_cond_always) { + if (op->info() != NULL) { + add_debug_info_for_branch(op->info()); + } + } else { + assert(op->in_opr1() != LIR_OprFact::illegalOpr && op->in_opr2() != LIR_OprFact::illegalOpr, "conditional branches must have legal operands"); + } + bool is_unordered = (op->ublock() == op->block()); + emit_branch(condition, op->in_opr1(), op->in_opr2(), *op->label(), /* is_far */ true, is_unordered); +} + +void LIR_Assembler::emit_branch(LIR_Condition cmp_flag, LIR_Opr cmp1, LIR_Opr cmp2, Label& label, + bool is_far, bool is_unordered) { + + if (cmp_flag == lir_cond_always) { + __ j(label); + return; + } + + if (cmp1->is_cpu_register()) { + Register reg1 = as_reg(cmp1); + if (cmp2->is_cpu_register()) { + Register reg2 = as_reg(cmp2); + __ c1_cmp_branch(cmp_flag, reg1, reg2, label, cmp1->type(), is_far); + } else if (cmp2->is_constant()) { + const2reg_helper(cmp2); + __ c1_cmp_branch(cmp_flag, reg1, t0, label, cmp2->type(), is_far); + } else { + ShouldNotReachHere(); + } + } else if (cmp1->is_single_fpu()) { + assert(cmp2->is_single_fpu(), "expect single float register"); + __ c1_float_cmp_branch(cmp_flag, cmp1->as_float_reg(), cmp2->as_float_reg(), label, is_far, is_unordered); + } else if (cmp1->is_double_fpu()) { + assert(cmp2->is_double_fpu(), "expect double float register"); + __ c1_float_cmp_branch(cmp_flag | C1_MacroAssembler::c1_double_branch_mask, + cmp1->as_double_reg(), cmp2->as_double_reg(), label, is_far, is_unordered); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { + LIR_Opr src = op->in_opr(); + LIR_Opr dest = op->result_opr(); + + switch (op->bytecode()) { + case Bytecodes::_i2f: + __ fcvt_s_w(dest->as_float_reg(), src->as_register()); break; + case Bytecodes::_i2d: + __ fcvt_d_w(dest->as_double_reg(), src->as_register()); break; + case Bytecodes::_l2d: + __ fcvt_d_l(dest->as_double_reg(), src->as_register_lo()); break; + case Bytecodes::_l2f: + __ fcvt_s_l(dest->as_float_reg(), src->as_register_lo()); break; + case Bytecodes::_f2d: + __ fcvt_d_s(dest->as_double_reg(), src->as_float_reg()); break; + case Bytecodes::_d2f: + __ fcvt_s_d(dest->as_float_reg(), src->as_double_reg()); break; + case Bytecodes::_i2c: + __ zero_extend(dest->as_register(), src->as_register(), 16); break; + case Bytecodes::_i2l: + __ addw(dest->as_register_lo(), src->as_register(), zr); break; + case Bytecodes::_i2s: + __ sign_extend(dest->as_register(), src->as_register(), 16); break; + case Bytecodes::_i2b: + __ sign_extend(dest->as_register(), src->as_register(), 8); break; + case Bytecodes::_l2i: + _masm->block_comment("FIXME: This coulde be no-op"); + __ addw(dest->as_register(), src->as_register_lo(), zr); break; + case Bytecodes::_d2l: + __ fcvt_l_d_safe(dest->as_register_lo(), src->as_double_reg()); break; + case Bytecodes::_f2i: + __ fcvt_w_s_safe(dest->as_register(), src->as_float_reg()); break; + case Bytecodes::_f2l: + __ fcvt_l_s_safe(dest->as_register_lo(), src->as_float_reg()); break; + case Bytecodes::_d2i: + __ fcvt_w_d_safe(dest->as_register(), src->as_double_reg()); break; + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { + if (op->init_check()) { + __ lbu(t0, Address(op->klass()->as_register(), + InstanceKlass::init_state_offset())); + __ mvw(t1, InstanceKlass::fully_initialized); + add_debug_info_for_null_check_here(op->stub()->info()); + __ bne(t0, t1, *op->stub()->entry(), /* is_far */ true); + } + + __ allocate_object(op->obj()->as_register(), + op->tmp1()->as_register(), + op->tmp2()->as_register(), + op->header_size(), + op->object_size(), + op->klass()->as_register(), + *op->stub()->entry()); + + __ bind(*op->stub()->continuation()); +} + +void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { + Register len = op->len()->as_register(); + + if (UseSlowPath || + (!UseFastNewObjectArray && is_reference_type(op->type())) || + (!UseFastNewTypeArray && !is_reference_type(op->type()))) { + __ j(*op->stub()->entry()); + } else { + Register tmp1 = op->tmp1()->as_register(); + Register tmp2 = op->tmp2()->as_register(); + Register tmp3 = op->tmp3()->as_register(); + if (len == tmp1) { + tmp1 = tmp3; + } else if (len == tmp2) { + tmp2 = tmp3; + } else if (len == tmp3) { + // everything is ok + } else { + __ mv(tmp3, len); + } + __ allocate_array(op->obj()->as_register(), + len, + tmp1, + tmp2, + arrayOopDesc::header_size(op->type()), + array_element_size(op->type()), + op->klass()->as_register(), + *op->stub()->entry()); + } + __ bind(*op->stub()->continuation()); +} + +void LIR_Assembler::type_profile_helper(Register mdo, ciMethodData *md, ciProfileData *data, + Register recv, Label* update_done) { + for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { + Label next_test; + // See if the receiver is receiver[n]. + __ ld(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); + __ bne(recv, t1, next_test); + Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); + __ add_memory_int64(data_addr, DataLayout::counter_increment); + __ j(*update_done); + __ bind(next_test); + } + + // Didn't find receiver; find next empty slot and fill it in + for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { + Label next_test; + Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))); + __ ld(t1, recv_addr); + __ bnez(t1, next_test); + __ sd(recv, recv_addr); + __ li(t1, DataLayout::counter_increment); + __ sd(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)))); + __ j(*update_done); + __ bind(next_test); + } +} + +void LIR_Assembler::data_check(LIR_OpTypeCheck *op, ciMethodData **md, ciProfileData **data) { + ciMethod* method = op->profiled_method(); + assert(method != NULL, "Should have method"); + int bci = op->profiled_bci(); + *md = method->method_data_or_null(); + guarantee(*md != NULL, "Sanity"); + *data = ((*md)->bci_to_data(bci)); + assert(*data != NULL, "need data for type check"); + assert((*data)->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); +} + +void LIR_Assembler::typecheck_helper_slowcheck(ciKlass *k, Register obj, Register Rtmp1, + Register k_RInfo, Register klass_RInfo, + Label *failure_target, Label *success_target) { + // get object class + // not a safepoint as obj null check happens earlier + __ load_klass(klass_RInfo, obj); + if (k->is_loaded()) { + // See if we get an immediate positive hit + __ ld(t0, Address(klass_RInfo, int64_t(k->super_check_offset()))); + if ((juint)in_bytes(Klass::secondary_super_cache_offset()) != k->super_check_offset()) { + __ bne(k_RInfo, t0, *failure_target, /* is_far */ true); + // successful cast, fall through to profile or jump + } else { + // See if we get an immediate positive hit + __ beq(k_RInfo, t0, *success_target); + // check for self + __ beq(klass_RInfo, k_RInfo, *success_target); + + __ addi(sp, sp, -2 * wordSize); // 2: store k_RInfo and klass_RInfo + __ sd(k_RInfo, Address(sp, 0)); // sub klass + __ sd(klass_RInfo, Address(sp, wordSize)); // super klass + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + // load result to k_RInfo + __ ld(k_RInfo, Address(sp, 0)); + __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo + // result is a boolean + __ beqz(k_RInfo, *failure_target, /* is_far */ true); + // successful cast, fall through to profile or jump + } + } else { + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); + // call out-of-line instance of __ check_klass_subtytpe_slow_path(...) + __ addi(sp, sp, -2 * wordSize); // 2: store k_RInfo and klass_RInfo + __ sd(klass_RInfo, Address(sp, wordSize)); // sub klass + __ sd(k_RInfo, Address(sp, 0)); // super klass + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + // load result to k_RInfo + __ ld(k_RInfo, Address(sp, 0)); + __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo + // result is a boolean + __ beqz(k_RInfo, *failure_target, /* is_far */ true); + // successful cast, fall thriugh to profile or jump + } +} + +void LIR_Assembler::profile_object(ciMethodData* md, ciProfileData* data, Register obj, + Register klass_RInfo, Label* obj_is_null) { + Label not_null; + __ bnez(obj, not_null); + // Object is null, update MDO and exit + Register mdo = klass_RInfo; + __ mov_metadata(mdo, md->constant_encoding()); + Address data_addr = __ form_address(t1, mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset())); + __ lbu(t0, data_addr); + __ ori(t0, t0, BitData::null_seen_byte_constant()); + __ sb(t0, data_addr); + __ j(*obj_is_null); + __ bind(not_null); +} + +void LIR_Assembler::typecheck_loaded(LIR_OpTypeCheck *op, ciKlass* k, Register k_RInfo) { + if (!k->is_loaded()) { + klass2reg_with_patching(k_RInfo, op->info_for_patch()); + } else { + __ mov_metadata(k_RInfo, k->constant_encoding()); + } +} + +void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { + Register obj = op->object()->as_register(); + Register k_RInfo = op->tmp1()->as_register(); + Register klass_RInfo = op->tmp2()->as_register(); + Register dst = op->result_opr()->as_register(); + ciKlass* k = op->klass(); + Register Rtmp1 = noreg; + + // check if it needs to be profiled + ciMethodData* md = NULL; + ciProfileData* data = NULL; + + const bool should_profile = op->should_profile(); + if (should_profile) { + data_check(op, &md, &data); + } + Label profile_cast_success, profile_cast_failure; + Label *success_target = should_profile ? &profile_cast_success : success; + Label *failure_target = should_profile ? &profile_cast_failure : failure; + + if (obj == k_RInfo) { + k_RInfo = dst; + } else if (obj == klass_RInfo) { + klass_RInfo = dst; + } + if (k->is_loaded() && !UseCompressedClassPointers) { + select_different_registers(obj, dst, k_RInfo, klass_RInfo); + } else { + Rtmp1 = op->tmp3()->as_register(); + select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); + } + + assert_different_registers(obj, k_RInfo, klass_RInfo); + + if (should_profile) { + profile_object(md, data, obj, klass_RInfo, obj_is_null); + } else { + __ beqz(obj, *obj_is_null); + } + + typecheck_loaded(op, k, k_RInfo); + __ verify_oop(obj); + + if (op->fast_check()) { + // get object class + // not a safepoint as obj null check happens earlier + __ load_klass(t0, obj); + __ bne(t0, k_RInfo, *failure_target, /* is_far */ true); + // successful cast, fall through to profile or jump + } else { + typecheck_helper_slowcheck(k, obj, Rtmp1, k_RInfo, klass_RInfo, failure_target, success_target); + } + if (should_profile) { + type_profile(obj, md, klass_RInfo, k_RInfo, data, success, failure, profile_cast_success, profile_cast_failure); + } + __ j(*success); +} + +void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { + const bool should_profile = op->should_profile(); + + LIR_Code code = op->code(); + if (code == lir_store_check) { + typecheck_lir_store(op, should_profile); + } else if (code == lir_checkcast) { + Register obj = op->object()->as_register(); + Register dst = op->result_opr()->as_register(); + Label success; + emit_typecheck_helper(op, &success, op->stub()->entry(), &success); + __ bind(success); + if (dst != obj) { + __ mv(dst, obj); + } + } else if (code == lir_instanceof) { + Register obj = op->object()->as_register(); + Register dst = op->result_opr()->as_register(); + Label success, failure, done; + emit_typecheck_helper(op, &success, &failure, &failure); + __ bind(failure); + __ mv(dst, zr); + __ j(done); + __ bind(success); + __ mv(dst, 1); + __ bind(done); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { + assert(VM_Version::supports_cx8(), "wrong machine"); + Register addr; + if (op->addr()->is_register()) { + addr = as_reg(op->addr()); + } else { + assert(op->addr()->is_address(), "what else?"); + LIR_Address* addr_ptr = op->addr()->as_address_ptr(); + assert(addr_ptr->disp() == 0, "need 0 disp"); + assert(addr_ptr->index() == LIR_Opr::illegalOpr(), "need 0 index"); + addr = as_reg(addr_ptr->base()); + } + Register newval = as_reg(op->new_value()); + Register cmpval = as_reg(op->cmp_value()); + + if (op->code() == lir_cas_obj) { + if (UseCompressedOops) { + Register tmp1 = op->tmp1()->as_register(); + assert(op->tmp1()->is_valid(), "must be"); + __ encode_heap_oop(tmp1, cmpval); + cmpval = tmp1; + __ encode_heap_oop(t1, newval); + newval = t1; + caswu(addr, newval, cmpval); + } else { + casl(addr, newval, cmpval); + } + } else if (op->code() == lir_cas_int) { + casw(addr, newval, cmpval); + } else { + casl(addr, newval, cmpval); + } +} + +void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op* op) { + switch (code) { + case lir_abs: __ fabs_d(dest->as_double_reg(), value->as_double_reg()); break; + case lir_sqrt: __ fsqrt_d(dest->as_double_reg(), value->as_double_reg()); break; + default: ShouldNotReachHere(); + } +} + +void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst) { + assert(left->is_single_cpu() || left->is_double_cpu(), "expect single or double register"); + Register Rleft = left->is_single_cpu() ? left->as_register() : left->as_register_lo(); + if (dst->is_single_cpu()) { + Register Rdst = dst->as_register(); + if (right->is_constant()) { + int right_const = right->as_jint(); + if (Assembler::operand_valid_for_add_immediate(right_const)) { + logic_op_imm(Rdst, Rleft, right_const, code); + __ addw(Rdst, Rdst, zr); + } else { + __ mv(t0, right_const); + logic_op_reg32(Rdst, Rleft, t0, code); + } + } else { + Register Rright = right->is_single_cpu() ? right->as_register() : right->as_register_lo(); + logic_op_reg32(Rdst, Rleft, Rright, code); + } + } else { + Register Rdst = dst->as_register_lo(); + if (right->is_constant()) { + long right_const = right->as_jlong(); + if (Assembler::operand_valid_for_add_immediate(right_const)) { + logic_op_imm(Rdst, Rleft, right_const, code); + } else { + __ mv(t0, right_const); + logic_op_reg(Rdst, Rleft, t0, code); + } + } else { + Register Rright = right->is_single_cpu() ? right->as_register() : right->as_register_lo(); + logic_op_reg(Rdst, Rleft, Rright, code); + } + } +} + +void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr src, LIR_Opr result, LIR_Op2* op) { + ShouldNotCallThis(); +} + +void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst, LIR_Op2* op) { + if (code == lir_cmp_fd2i || code == lir_ucmp_fd2i) { + bool is_unordered_less = (code == lir_ucmp_fd2i); + if (left->is_single_fpu()) { + __ float_cmp(true, is_unordered_less ? -1 : 1, + left->as_float_reg(), right->as_float_reg(), dst->as_register()); + } else if (left->is_double_fpu()) { + __ float_cmp(false, is_unordered_less ? -1 : 1, + left->as_double_reg(), right->as_double_reg(), dst->as_register()); + } else { + ShouldNotReachHere(); + } + } else if (code == lir_cmp_l2i) { + __ cmp_l2i(dst->as_register(), left->as_register_lo(), right->as_register_lo()); + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::align_call(LIR_Code code) { + // With RVC a call instruction may get 2-byte aligned. + // The address of the call instruction needs to be 4-byte aligned to + // ensure that it does not span a cache line so that it can be patched. + __ align(4); +} + +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { + address call = __ trampoline_call(Address(op->addr(), rtype)); + if (call == NULL) { + bailout("trampoline stub overflow"); + return; + } + add_call_info(code_offset(), op->info()); +} + +void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { + address call = __ ic_call(op->addr()); + if (call == NULL) { + bailout("trampoline stub overflow"); + return; + } + add_call_info(code_offset(), op->info()); +} + +void LIR_Assembler::emit_static_call_stub() { + address call_pc = __ pc(); + assert((__ offset() % 4) == 0, "bad alignment"); + address stub = __ start_a_stub(call_stub_size()); + if (stub == NULL) { + bailout("static call stub overflow"); + return; + } + + int start = __ offset(); + + __ relocate(static_stub_Relocation::spec(call_pc)); + __ emit_static_call_stub(); + + assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size() + <= call_stub_size(), "stub too big"); + __ end_a_stub(); +} + +void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { + assert(exceptionOop->as_register() == x10, "must match"); + assert(exceptionPC->as_register() == x13, "must match"); + + // exception object is not added to oop map by LinearScan + // (LinearScan assumes that no oops are in fixed registers) + info->add_register_oop(exceptionOop); + Runtime1::StubID unwind_id; + + // get current pc information + // pc is only needed if the method has an exception handler, the unwind code does not need it. + if (compilation()->debug_info_recorder()->last_pc_offset() == __ offset()) { + // As no instructions have been generated yet for this LIR node it's + // possible that an oop map already exists for the current offset. + // In that case insert an dummy NOP here to ensure all oop map PCs + // are unique. See JDK-8237483. + __ nop(); + } + int pc_for_athrow_offset = __ offset(); + InternalAddress pc_for_athrow(__ pc()); + int32_t off = 0; + __ la_patchable(exceptionPC->as_register(), pc_for_athrow, off); + __ addi(exceptionPC->as_register(), exceptionPC->as_register(), off); + add_call_info(pc_for_athrow_offset, info); // for exception handler + + __ verify_not_null_oop(x10); + // search an exception handler (x10: exception oop, x13: throwing pc) + if (compilation()->has_fpu_code()) { + unwind_id = Runtime1::handle_exception_id; + } else { + unwind_id = Runtime1::handle_exception_nofpu_id; + } + __ far_call(RuntimeAddress(Runtime1::entry_for(unwind_id))); + __ nop(); +} + +void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) { + assert(exceptionOop->as_register() == x10, "must match"); + __ j(_unwind_handler_entry); +} + +void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { + Register left_reg = left->is_single_cpu() ? left->as_register() : left->as_register_lo(); + Register dest_reg = dest->is_single_cpu() ? dest->as_register() : dest->as_register_lo(); + Register count_reg = count->as_register(); + if (dest->is_single_cpu()) { + assert (dest->type() == T_INT, "unexpected result type"); + assert (left->type() == T_INT, "unexpected left type"); + __ andi(t0, count_reg, 31); // should not shift more than 31 bits + switch (code) { + case lir_shl: __ sllw(dest_reg, left_reg, t0); break; + case lir_shr: __ sraw(dest_reg, left_reg, t0); break; + case lir_ushr: __ srlw(dest_reg, left_reg, t0); break; + default: ShouldNotReachHere(); + } + } else if (dest->is_double_cpu()) { + __ andi(t0, count_reg, 63); // should not shift more than 63 bits + switch (code) { + case lir_shl: __ sll(dest_reg, left_reg, t0); break; + case lir_shr: __ sra(dest_reg, left_reg, t0); break; + case lir_ushr: __ srl(dest_reg, left_reg, t0); break; + default: ShouldNotReachHere(); + } + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { + Register left_reg = left->is_single_cpu() ? left->as_register() : left->as_register_lo(); + Register dest_reg = dest->is_single_cpu() ? dest->as_register() : dest->as_register_lo(); + if (dest->is_single_cpu()) { + assert (dest->type() == T_INT, "unexpected result type"); + assert (left->type() == T_INT, "unexpected left type"); + count &= 0x1f; + if (count != 0) { + switch (code) { + case lir_shl: __ slliw(dest_reg, left_reg, count); break; + case lir_shr: __ sraiw(dest_reg, left_reg, count); break; + case lir_ushr: __ srliw(dest_reg, left_reg, count); break; + default: ShouldNotReachHere(); + } + } else { + move_regs(left_reg, dest_reg); + } + } else if (dest->is_double_cpu()) { + count &= 0x3f; + if (count != 0) { + switch (code) { + case lir_shl: __ slli(dest_reg, left_reg, count); break; + case lir_shr: __ srai(dest_reg, left_reg, count); break; + case lir_ushr: __ srli(dest_reg, left_reg, count); break; + default: ShouldNotReachHere(); + } + } else { + move_regs(left->as_register_lo(), dest->as_register_lo()); + } + } else { + ShouldNotReachHere(); + } +} + +void LIR_Assembler::emit_lock(LIR_OpLock* op) { + Register obj = op->obj_opr()->as_register(); // may not be an oop + Register hdr = op->hdr_opr()->as_register(); + Register lock = op->lock_opr()->as_register(); + if (UseHeavyMonitors) { + __ j(*op->stub()->entry()); + } else if (op->code() == lir_lock) { + assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); + // add debug info for NullPointerException only if one is possible + int null_check_offset = __ lock_object(hdr, obj, lock, *op->stub()->entry()); + if (op->info() != NULL) { + add_debug_info_for_null_check(null_check_offset, op->info()); + } + } else if (op->code() == lir_unlock) { + assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); + __ unlock_object(hdr, obj, lock, *op->stub()->entry()); + } else { + Unimplemented(); + } + __ bind(*op->stub()->continuation()); +} + +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + + if (UseCompressedClassPointers) { + __ lwu(result, Address(obj, oopDesc::klass_offset_in_bytes())); + __ decode_klass_not_null(result); + } else { + __ ld(result, Address(obj, oopDesc::klass_offset_in_bytes())); + } +} + +void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { + ciMethod* method = op->profiled_method(); + int bci = op->profiled_bci(); + + // Update counter for all call types + ciMethodData* md = method->method_data_or_null(); + guarantee(md != NULL, "Sanity"); + ciProfileData* data = md->bci_to_data(bci); + assert(data != NULL && data->is_CounterData(), "need CounterData for calls"); + assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); + Register mdo = op->mdo()->as_register(); + __ mov_metadata(mdo, md->constant_encoding()); + Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); + // Perform additional virtual call profiling for invokevirtual and + // invokeinterface bytecodes + if (op->should_profile_receiver_type()) { + assert(op->recv()->is_single_cpu(), "recv must be allocated"); + Register recv = op->recv()->as_register(); + assert_different_registers(mdo, recv); + assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls"); + ciKlass* known_klass = op->known_holder(); + if (C1OptimizeVirtualCallProfiling && known_klass != NULL) { + // We know the type that will be seen at this call site; we can + // statically update the MethodData* rather than needing to do + // dynamic tests on the receiver type + // NOTE: we should probably put a lock around this search to + // avoid collisions by concurrent compilations + ciVirtualCallData* vc_data = (ciVirtualCallData*) data; + uint i; + for (i = 0; i < VirtualCallData::row_limit(); i++) { + ciKlass* receiver = vc_data->receiver(i); + if (known_klass->equals(receiver)) { + Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); + __ add_memory_int64(data_addr, DataLayout::counter_increment); + return; + } + } + + // Receiver type not found in profile data; select an empty slot + // Note that this is less efficient than it should be because it + // always does a write to the receiver part of the + // VirtualCallData rather than just the first time + for (i = 0; i < VirtualCallData::row_limit(); i++) { + ciKlass* receiver = vc_data->receiver(i); + if (receiver == NULL) { + Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); + __ mov_metadata(t1, known_klass->constant_encoding()); + __ sd(t1, recv_addr); + Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); + __ add_memory_int64(data_addr, DataLayout::counter_increment); + return; + } + } + } else { + __ load_klass(recv, recv); + Label update_done; + type_profile_helper(mdo, md, data, recv, &update_done); + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + __ add_memory_int64(counter_addr, DataLayout::counter_increment); + + __ bind(update_done); + } + } else { + // Static call + __ add_memory_int64(counter_addr, DataLayout::counter_increment); + } +} + +void LIR_Assembler::emit_delay(LIR_OpDelay*) { Unimplemented(); } + +void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) { + __ la(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no)); +} + +void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { Unimplemented(); } + +void LIR_Assembler::check_conflict(ciKlass* exact_klass, intptr_t current_klass, + Register tmp, Label &next, Label &none, + Address mdo_addr) { + if (exact_klass == NULL || TypeEntries::is_type_none(current_klass)) { + if (exact_klass != NULL) { + __ mov_metadata(tmp, exact_klass->constant_encoding()); + } else { + __ load_klass(tmp, tmp); + } + + __ ld(t1, mdo_addr); + __ xorr(tmp, tmp, t1); + __ andi(t0, tmp, TypeEntries::type_klass_mask); + // klass seen before, nothing to do. The unknown bit may have been + // set already but no need to check. + __ beqz(t0, next); + + // already unknown. Nothing to do anymore. + __ andi(t0, tmp, TypeEntries::type_unknown); + __ bnez(t0, next); + + if (TypeEntries::is_type_none(current_klass)) { + __ beqz(t1, none); + __ li(t0, (u1)TypeEntries::null_seen); + __ beq(t0, t1, none); + // There is a chance that the checks above (re-reading profiling + // data from memory) fail if another thread has just set the + // profiling to this obj's klass + __ membar(MacroAssembler::LoadLoad); + __ ld(t1, mdo_addr); + __ xorr(tmp, tmp, t1); + __ andi(t0, tmp, TypeEntries::type_klass_mask); + __ beqz(t0, next); + } + } else { + assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); + + __ ld(tmp, mdo_addr); + // already unknown. Nothing to do anymore. + __ andi(t0, tmp, TypeEntries::type_unknown); + __ bnez(t0, next); + } + + // different than before. Cannot keep accurate profile. + __ ld(t1, mdo_addr); + __ ori(t1, t1, TypeEntries::type_unknown); + __ sd(t1, mdo_addr); + + if (TypeEntries::is_type_none(current_klass)) { + __ j(next); + + __ bind(none); + // first time here. Set profile type. + __ sd(tmp, mdo_addr); + } +} + +void LIR_Assembler::check_no_conflict(ciKlass* exact_klass, intptr_t current_klass, Register tmp, + Address mdo_addr, Label &next) { + // There's a single possible klass at this profile point + assert(exact_klass != NULL, "should be"); + if (TypeEntries::is_type_none(current_klass)) { + __ mov_metadata(tmp, exact_klass->constant_encoding()); + __ ld(t1, mdo_addr); + __ xorr(tmp, tmp, t1); + __ andi(t0, tmp, TypeEntries::type_klass_mask); + __ beqz(t0, next); +#ifdef ASSERT + { + Label ok; + __ ld(t0, mdo_addr); + __ beqz(t0, ok); + __ li(t1, (u1)TypeEntries::null_seen); + __ beq(t0, t1, ok); + // may have been set by another thread + __ membar(MacroAssembler::LoadLoad); + __ mov_metadata(t0, exact_klass->constant_encoding()); + __ ld(t1, mdo_addr); + __ xorr(t1, t0, t1); + __ andi(t1, t1, TypeEntries::type_mask); + __ beqz(t1, ok); + + __ stop("unexpected profiling mismatch"); + __ bind(ok); + } +#endif + // first time here. Set profile type. + __ sd(tmp, mdo_addr); + } else { + assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); + + __ ld(tmp, mdo_addr); + // already unknown. Nothing to do anymore. + __ andi(t0, tmp, TypeEntries::type_unknown); + __ bnez(t0, next); + + __ ori(tmp, tmp, TypeEntries::type_unknown); + __ sd(tmp, mdo_addr); + } +} + +void LIR_Assembler::check_null(Register tmp, Label &update, intptr_t current_klass, + Address mdo_addr, bool do_update, Label &next) { + __ bnez(tmp, update); + if (!TypeEntries::was_null_seen(current_klass)) { + __ ld(t1, mdo_addr); + __ ori(t1, t1, TypeEntries::null_seen); + __ sd(t1, mdo_addr); + } + if (do_update) { + __ j(next); + } +} + +void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { + COMMENT("emit_profile_type {"); + Register obj = op->obj()->as_register(); + Register tmp = op->tmp()->as_pointer_register(); + Address mdo_addr = as_Address(op->mdp()->as_address_ptr()); + ciKlass* exact_klass = op->exact_klass(); + intptr_t current_klass = op->current_klass(); + bool not_null = op->not_null(); + bool no_conflict = op->no_conflict(); + + Label update, next, none; + + bool do_null = !not_null; + bool exact_klass_set = exact_klass != NULL && ciTypeEntries::valid_ciklass(current_klass) == exact_klass; + bool do_update = !TypeEntries::is_type_unknown(current_klass) && !exact_klass_set; + + assert(do_null || do_update, "why are we here?"); + assert(!TypeEntries::was_null_seen(current_klass) || do_update, "why are we here?"); + assert_different_registers(tmp, t0, t1, mdo_addr.base()); + + __ verify_oop(obj); + + if (tmp != obj) { + __ mv(tmp, obj); + } + if (do_null) { + check_null(tmp, update, current_klass, mdo_addr, do_update, next); +#ifdef ASSERT + } else { + __ bnez(tmp, update); + __ stop("unexpected null obj"); +#endif + } + + __ bind(update); + + if (do_update) { +#ifdef ASSERT + if (exact_klass != NULL) { + check_exact_klass(tmp, exact_klass); + } +#endif + if (!no_conflict) { + check_conflict(exact_klass, current_klass, tmp, next, none, mdo_addr); + } else { + check_no_conflict(exact_klass, current_klass, tmp, mdo_addr, next); + } + + __ bind(next); + } + COMMENT("} emit_profile_type"); +} + +void LIR_Assembler::align_backward_branch_target() { } + +void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) { + // tmp must be unused + assert(tmp->is_illegal(), "wasting a register if tmp is allocated"); + + if (left->is_single_cpu()) { + assert(dest->is_single_cpu(), "expect single result reg"); + __ negw(dest->as_register(), left->as_register()); + } else if (left->is_double_cpu()) { + assert(dest->is_double_cpu(), "expect double result reg"); + __ neg(dest->as_register_lo(), left->as_register_lo()); + } else if (left->is_single_fpu()) { + assert(dest->is_single_fpu(), "expect single float result reg"); + __ fneg_s(dest->as_float_reg(), left->as_float_reg()); + } else { + assert(left->is_double_fpu(), "expect double float operand reg"); + assert(dest->is_double_fpu(), "expect double float result reg"); + __ fneg_d(dest->as_double_reg(), left->as_double_reg()); + } +} + + +void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { + if (patch_code != lir_patch_none) { + deoptimize_trap(info); + return; + } + + LIR_Address* adr = addr->as_address_ptr(); + Register dst = dest->as_register_lo(); + + assert_different_registers(dst, t0); + if (adr->base()->is_valid() && dst == adr->base()->as_pointer_register() && (!adr->index()->is_cpu_register())) { + int scale = adr->scale(); + intptr_t offset = adr->disp(); + LIR_Opr index_op = adr->index(); + if (index_op->is_constant()) { + offset += ((intptr_t)index_op->as_constant_ptr()->as_jint()) << scale; + } + + if (!is_imm_in_range(offset, 12, 0)) { + __ la(t0, as_Address(adr)); + __ mv(dst, t0); + return; + } + } + + __ la(dst, as_Address(adr)); +} + + +void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { + assert(!tmp->is_valid(), "don't need temporary"); + + CodeBlob *cb = CodeCache::find_blob(dest); + if (cb != NULL) { + __ far_call(RuntimeAddress(dest)); + } else { + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(dest), offset); + __ jalr(x1, t0, offset); + } + + if (info != NULL) { + add_call_info_here(info); + } +} + +void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { + if (dest->is_address() || src->is_address()) { + move_op(src, dest, type, lir_patch_none, info, /* pop_fpu_stack */ false, /* wide */ false); + } else { + ShouldNotReachHere(); + } +} + +#ifdef ASSERT +// emit run-time assertion +void LIR_Assembler::emit_assert(LIR_OpAssert* op) { + assert(op->code() == lir_assert, "must be"); + + Label ok; + if (op->in_opr1()->is_valid()) { + assert(op->in_opr2()->is_valid(), "both operands must be valid"); + bool is_unordered = false; + LIR_Condition cond = op->condition(); + emit_branch(cond, op->in_opr1(), op->in_opr2(), ok, /* is_far */ false, + /* is_unordered */(cond == lir_cond_greaterEqual || cond == lir_cond_greater) ? false : true); + } else { + assert(op->in_opr2()->is_illegal(), "both operands must be illegal"); + assert(op->condition() == lir_cond_always, "no other conditions allowed"); + } + + if (op->halt()) { + const char* str = __ code_string(op->msg()); + __ stop(str); + } else { + breakpoint(); + } + __ bind(ok); +} +#endif + +#ifndef PRODUCT +#define COMMENT(x) do { __ block_comment(x); } while (0) +#else +#define COMMENT(x) +#endif + +void LIR_Assembler::membar() { + COMMENT("membar"); + __ membar(MacroAssembler::AnyAny); +} + +void LIR_Assembler::membar_acquire() { + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); +} + +void LIR_Assembler::membar_release() { + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); +} + +void LIR_Assembler::membar_loadload() { + __ membar(MacroAssembler::LoadLoad); +} + +void LIR_Assembler::membar_storestore() { + __ membar(MacroAssembler::StoreStore); +} + +void LIR_Assembler::membar_loadstore() { __ membar(MacroAssembler::LoadStore); } + +void LIR_Assembler::membar_storeload() { __ membar(MacroAssembler::StoreLoad); } + +void LIR_Assembler::on_spin_wait() { + Unimplemented(); +} + +void LIR_Assembler::get_thread(LIR_Opr result_reg) { + __ mv(result_reg->as_register(), xthread); +} + +void LIR_Assembler::peephole(LIR_List *lir) {} + +void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp_op) { + Address addr = as_Address(src->as_address_ptr()); + BasicType type = src->type(); + bool is_oop = is_reference_type(type); + + get_op(type); + + switch (code) { + case lir_xadd: + { + RegisterOrConstant inc; + Register tmp = as_reg(tmp_op); + Register dst = as_reg(dest); + if (data->is_constant()) { + inc = RegisterOrConstant(as_long(data)); + assert_different_registers(dst, addr.base(), tmp); + assert_different_registers(tmp, t0); + } else { + inc = RegisterOrConstant(as_reg(data)); + assert_different_registers(inc.as_register(), dst, addr.base(), tmp); + } + __ la(tmp, addr); + (_masm->*add)(dst, inc, tmp); + break; + } + case lir_xchg: + { + Register tmp = tmp_op->as_register(); + Register obj = as_reg(data); + Register dst = as_reg(dest); + if (is_oop && UseCompressedOops) { + __ encode_heap_oop(t0, obj); + obj = t0; + } + assert_different_registers(obj, addr.base(), tmp, dst); + __ la(tmp, addr); + (_masm->*xchg)(dst, obj, tmp); + if (is_oop && UseCompressedOops) { + __ decode_heap_oop(dst); + } + } + break; + default: + ShouldNotReachHere(); + } + __ membar(MacroAssembler::AnyAny); +} + +int LIR_Assembler::array_element_size(BasicType type) const { + int elem_size = type2aelembytes(type); + return exact_log2(elem_size); +} + +// helper functions which checks for overflow and sets bailout if it +// occurs. Always returns a valid embeddable pointer but in the +// bailout case the pointer won't be to unique storage. +address LIR_Assembler::float_constant(float f) { + address const_addr = __ float_constant(f); + if (const_addr == NULL) { + bailout("const section overflow"); + return __ code()->consts()->start(); + } else { + return const_addr; + } +} + +address LIR_Assembler::double_constant(double d) { + address const_addr = __ double_constant(d); + if (const_addr == NULL) { + bailout("const section overflow"); + return __ code()->consts()->start(); + } else { + return const_addr; + } +} + +address LIR_Assembler::int_constant(jlong n) { + address const_addr = __ long_constant(n); + if (const_addr == NULL) { + bailout("const section overflow"); + return __ code()->consts()->start(); + } else { + return const_addr; + } +} + +void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { + __ cmpxchg(addr, cmpval, newval, Assembler::int32, Assembler::aq /* acquire */, + Assembler::rl /* release */, t0, true /* result as bool */); + __ seqz(t0, t0); // cmpxchg not equal, set t0 to 1 + __ membar(MacroAssembler::AnyAny); +} + +void LIR_Assembler::caswu(Register addr, Register newval, Register cmpval) { + __ cmpxchg(addr, cmpval, newval, Assembler::uint32, Assembler::aq /* acquire */, + Assembler::rl /* release */, t0, true /* result as bool */); + __ seqz(t0, t0); // cmpxchg not equal, set t0 to 1 + __ membar(MacroAssembler::AnyAny); +} + +void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) { + __ cmpxchg(addr, cmpval, newval, Assembler::int64, Assembler::aq /* acquire */, + Assembler::rl /* release */, t0, true /* result as bool */); + __ seqz(t0, t0); // cmpxchg not equal, set t0 to 1 + __ membar(MacroAssembler::AnyAny); +} + +void LIR_Assembler::deoptimize_trap(CodeEmitInfo *info) { + address target = NULL; + + switch (patching_id(info)) { + case PatchingStub::access_field_id: + target = Runtime1::entry_for(Runtime1::access_field_patching_id); + break; + case PatchingStub::load_klass_id: + target = Runtime1::entry_for(Runtime1::load_klass_patching_id); + break; + case PatchingStub::load_mirror_id: + target = Runtime1::entry_for(Runtime1::load_mirror_patching_id); + break; + case PatchingStub::load_appendix_id: + target = Runtime1::entry_for(Runtime1::load_appendix_patching_id); + break; + default: ShouldNotReachHere(); + } + + __ far_call(RuntimeAddress(target)); + add_call_info_here(info); +} + +void LIR_Assembler::check_exact_klass(Register tmp, ciKlass* exact_klass) { + Label ok; + __ load_klass(tmp, tmp); + __ mov_metadata(t0, exact_klass->constant_encoding()); + __ beq(tmp, t0, ok); + __ stop("exact klass and actual klass differ"); + __ bind(ok); +} + +void LIR_Assembler::get_op(BasicType type) { + switch (type) { + case T_INT: + xchg = &MacroAssembler::atomic_xchgalw; + add = &MacroAssembler::atomic_addalw; + break; + case T_LONG: + xchg = &MacroAssembler::atomic_xchgal; + add = &MacroAssembler::atomic_addal; + break; + case T_OBJECT: + case T_ARRAY: + if (UseCompressedOops) { + xchg = &MacroAssembler::atomic_xchgalwu; + add = &MacroAssembler::atomic_addalw; + } else { + xchg = &MacroAssembler::atomic_xchgal; + add = &MacroAssembler::atomic_addal; + } + break; + default: + ShouldNotReachHere(); + } +} + +// emit_opTypeCheck sub functions +void LIR_Assembler::typecheck_lir_store(LIR_OpTypeCheck* op, bool should_profile) { + Register value = op->object()->as_register(); + Register array = op->array()->as_register(); + Register k_RInfo = op->tmp1()->as_register(); + Register klass_RInfo = op->tmp2()->as_register(); + Register Rtmp1 = op->tmp3()->as_register(); + + CodeStub* stub = op->stub(); + + // check if it needs to be profiled + ciMethodData* md = NULL; + ciProfileData* data = NULL; + + if (should_profile) { + data_check(op, &md, &data); + } + Label profile_cast_success, profile_cast_failure, done; + Label *success_target = should_profile ? &profile_cast_success : &done; + Label *failure_target = should_profile ? &profile_cast_failure : stub->entry(); + + if (should_profile) { + profile_object(md, data, value, klass_RInfo, &done); + } else { + __ beqz(value, done); + } + + add_debug_info_for_null_check_here(op->info_for_exception()); + __ load_klass(k_RInfo, array); + __ load_klass(klass_RInfo, value); + + lir_store_slowcheck(k_RInfo, klass_RInfo, Rtmp1, success_target, failure_target); + + // fall through to the success case + if (should_profile) { + Register mdo = klass_RInfo; + Register recv = k_RInfo; + __ bind(profile_cast_success); + __ mov_metadata(mdo, md->constant_encoding()); + __ load_klass(recv, value); + type_profile_helper(mdo, md, data, recv, &done); + __ j(done); + + __ bind(profile_cast_failure); + __ mov_metadata(mdo, md->constant_encoding()); + Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); + __ ld(t1, counter_addr); + __ addi(t1, t1, -DataLayout::counter_increment); + __ sd(t1, counter_addr); + __ j(*stub->entry()); + } + + __ bind(done); +} + +void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) { + _masm->code_section()->relocate(adr, relocInfo::poll_type); + int pc_offset = code_offset(); + flush_debug_info(pc_offset); + info->record_debug_info(compilation()->debug_info_recorder(), pc_offset); + if (info->exception_handlers() != NULL) { + compilation()->add_exception_handlers_for_pco(pc_offset, info->exception_handlers()); + } +} + +void LIR_Assembler::type_profile(Register obj, ciMethodData* md, Register klass_RInfo, Register k_RInfo, + ciProfileData* data, Label* success, Label* failure, + Label& profile_cast_success, Label& profile_cast_failure) { + Register mdo = klass_RInfo; + Register recv = k_RInfo; + __ bind(profile_cast_success); + __ mov_metadata(mdo, md->constant_encoding()); + __ load_klass(recv, obj); + Label update_done; + type_profile_helper(mdo, md, data, recv, success); + __ j(*success); + + __ bind(profile_cast_failure); + __ mov_metadata(mdo, md->constant_encoding()); + Address counter_addr = __ form_address(t1, mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); + __ ld(t0, counter_addr); + __ addi(t0, t0, -DataLayout::counter_increment); + __ sd(t0, counter_addr); + __ j(*failure); +} + +void LIR_Assembler::lir_store_slowcheck(Register k_RInfo, Register klass_RInfo, Register Rtmp1, + Label* success_target, Label* failure_target) { + // get instance klass (it's already uncompressed) + __ ld(k_RInfo, Address(k_RInfo, ObjArrayKlass::element_klass_offset())); + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); + // call out-of-line instance of __ check_klass_subtype_slow_path(...) + __ addi(sp, sp, -2 * wordSize); // 2: store k_RInfo and klass_RInfo + __ sd(klass_RInfo, Address(sp, wordSize)); // sub klass + __ sd(k_RInfo, Address(sp, 0)); // super klass + __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + // load result to k_RInfo + __ ld(k_RInfo, Address(sp, 0)); + __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo + // result is a boolean + __ beqz(k_RInfo, *failure_target, /* is_far */ true); +} + +void LIR_Assembler::const2reg_helper(LIR_Opr src) { + switch (src->as_constant_ptr()->type()) { + case T_INT: + case T_ADDRESS: + case T_OBJECT: + case T_ARRAY: + case T_METADATA: + const2reg(src, FrameMap::t0_opr, lir_patch_none, NULL); + break; + case T_LONG: + const2reg(src, FrameMap::t0_long_opr, lir_patch_none, NULL); + break; + case T_FLOAT: + case T_DOUBLE: + default: + ShouldNotReachHere(); + } +} + +void LIR_Assembler::logic_op_reg32(Register dst, Register left, Register right, LIR_Code code) { + switch (code) { + case lir_logic_and: __ andrw(dst, left, right); break; + case lir_logic_or: __ orrw (dst, left, right); break; + case lir_logic_xor: __ xorrw(dst, left, right); break; + default: ShouldNotReachHere(); + } +} + +void LIR_Assembler::logic_op_reg(Register dst, Register left, Register right, LIR_Code code) { + switch (code) { + case lir_logic_and: __ andr(dst, left, right); break; + case lir_logic_or: __ orr (dst, left, right); break; + case lir_logic_xor: __ xorr(dst, left, right); break; + default: ShouldNotReachHere(); + } +} + +void LIR_Assembler::logic_op_imm(Register dst, Register left, int right, LIR_Code code) { + switch (code) { + case lir_logic_and: __ andi(dst, left, right); break; + case lir_logic_or: __ ori (dst, left, right); break; + case lir_logic_xor: __ xori(dst, left, right); break; + default: ShouldNotReachHere(); + } +} + +void LIR_Assembler::store_parameter(Register r, int offset_from_rsp_in_words) { + assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); + int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; + assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); + __ sd(r, Address(sp, offset_from_rsp_in_bytes)); +} + +void LIR_Assembler::store_parameter(jint c, int offset_from_rsp_in_words) { + assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); + int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; + assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); + __ li(t0, c); + __ sd(t0, Address(sp, offset_from_rsp_in_bytes)); +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..051328c3a8a3f6f0a7fa780a2a02f238b173fe4c --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_LIRASSEMBLER_RISCV_HPP +#define CPU_RISCV_C1_LIRASSEMBLER_RISCV_HPP + +// ArrayCopyStub needs access to bailout +friend class ArrayCopyStub; + +private: + +#include "c1_LIRAssembler_arith_riscv.hpp" +#include "c1_LIRAssembler_arraycopy_riscv.hpp" + + int array_element_size(BasicType type) const; + + static Register as_reg(LIR_Opr op) { + return op->is_double_cpu() ? op->as_register_lo() : op->as_register(); + } + + Address as_Address(LIR_Address* addr, Register tmp); + + // helper functions which checks for overflow and sets bailout if it + // occurs. Always returns a valid embeddable pointer but in the + // bailout case the pointer won't be to unique storage. + address float_constant(float f); + address double_constant(double d); + address int_constant(jlong n); + + // Ensure we have a valid Address (base + offset) to a stack-slot. + Address stack_slot_address(int index, uint shift, int adjust = 0); + + // Record the type of the receiver in ReceiverTypeData + void type_profile_helper(Register mdo, + ciMethodData *md, ciProfileData *data, + Register recv, Label* update_done); + + void add_debug_info_for_branch(address adr, CodeEmitInfo* info); + + void casw(Register addr, Register newval, Register cmpval); + void caswu(Register addr, Register newval, Register cmpval); + void casl(Register addr, Register newval, Register cmpval); + + void poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info = NULL); + + void deoptimize_trap(CodeEmitInfo *info); + + enum { + // See emit_static_call_stub for detail + // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address) + _call_stub_size = 14 * NativeInstruction::instruction_size + + (NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size), + // See emit_exception_handler for detail + // verify_not_null_oop + far_call + should_not_reach_here + invalidate_registers(DEBUG_ONLY) + _exception_handler_size = DEBUG_ONLY(584) NOT_DEBUG(548), // or smaller + // See emit_deopt_handler for detail + // auipc (1) + far_jump (6 or 2) + _deopt_handler_size = 1 * NativeInstruction::instruction_size + + 6 * NativeInstruction::instruction_size // or smaller + }; + + void check_conflict(ciKlass* exact_klass, intptr_t current_klass, Register tmp, + Label &next, Label &none, Address mdo_addr); + void check_no_conflict(ciKlass* exact_klass, intptr_t current_klass, Register tmp, Address mdo_addr, Label &next); + + void check_exact_klass(Register tmp, ciKlass* exact_klass); + + void check_null(Register tmp, Label &update, intptr_t current_klass, Address mdo_addr, bool do_update, Label &next); + + void (MacroAssembler::*add)(Register prev, RegisterOrConstant incr, Register addr); + void (MacroAssembler::*xchg)(Register prev, Register newv, Register addr); + + void get_op(BasicType type); + + // emit_typecheck_helper sub functions + void data_check(LIR_OpTypeCheck *op, ciMethodData **md, ciProfileData **data); + void typecheck_helper_slowcheck(ciKlass* k, Register obj, Register Rtmp1, + Register k_RInfo, Register klass_RInfo, + Label* failure_target, Label* success_target); + void profile_object(ciMethodData* md, ciProfileData* data, Register obj, + Register klass_RInfo, Label* obj_is_null); + void typecheck_loaded(LIR_OpTypeCheck* op, ciKlass* k, Register k_RInfo); + + // emit_opTypeCheck sub functions + void typecheck_lir_store(LIR_OpTypeCheck* op, bool should_profile); + + void type_profile(Register obj, ciMethodData* md, Register klass_RInfo, Register k_RInfo, + ciProfileData* data, Label* success, Label* failure, + Label& profile_cast_success, Label& profile_cast_failure); + + void lir_store_slowcheck(Register k_RInfo, Register klass_RInfo, Register Rtmp1, + Label* success_target, Label* failure_target); + + void const2reg_helper(LIR_Opr src); + + void emit_branch(LIR_Condition cmp_flag, LIR_Opr cmp1, LIR_Opr cmp2, Label& label, bool is_far, bool is_unordered); + + void logic_op_reg32(Register dst, Register left, Register right, LIR_Code code); + void logic_op_reg(Register dst, Register left, Register right, LIR_Code code); + void logic_op_imm(Register dst, Register left, int right, LIR_Code code); + +public: + + void emit_cmove(LIR_Op4* op); + + void store_parameter(Register r, int offset_from_rsp_in_words); + void store_parameter(jint c, int offset_from_rsp_in_words); + +#endif // CPU_RISCV_C1_LIRASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e126f148cdf2bca1492aa42efa89e1d2bb4fea53 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp @@ -0,0 +1,1075 @@ +/* + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "c1/c1_Compilation.hpp" +#include "c1/c1_FrameMap.hpp" +#include "c1/c1_Instruction.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_LIRGenerator.hpp" +#include "c1/c1_Runtime1.hpp" +#include "c1/c1_ValueStack.hpp" +#include "ci/ciArray.hpp" +#include "ci/ciObjArrayKlass.hpp" +#include "ci/ciTypeArrayKlass.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + +#ifdef ASSERT +#define __ gen()->lir(__FILE__, __LINE__)-> +#else +#define __ gen()->lir()-> +#endif + +// Item will be loaded into a byte register; Intel only +void LIRItem::load_byte_item() { + load_item(); +} + + +void LIRItem::load_nonconstant() { + LIR_Opr r = value()->operand(); + if (r->is_constant()) { + _result = r; + } else { + load_item(); + } +} + +//-------------------------------------------------------------- +// LIRGenerator +//-------------------------------------------------------------- + + +LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::r10_oop_opr; } +LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::r13_opr; } +LIR_Opr LIRGenerator::divInOpr() { Unimplemented(); return LIR_OprFact::illegalOpr; } +LIR_Opr LIRGenerator::divOutOpr() { Unimplemented(); return LIR_OprFact::illegalOpr; } +LIR_Opr LIRGenerator::remOutOpr() { Unimplemented(); return LIR_OprFact::illegalOpr; } +LIR_Opr LIRGenerator::shiftCountOpr() { Unimplemented(); return LIR_OprFact::illegalOpr; } +LIR_Opr LIRGenerator::syncLockOpr() { return new_register(T_INT); } +LIR_Opr LIRGenerator::syncTempOpr() { return FrameMap::r10_opr; } +LIR_Opr LIRGenerator::getThreadTemp() { return LIR_OprFact::illegalOpr; } + + +LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) { + LIR_Opr opr; + switch (type->tag()) { + case intTag: opr = FrameMap::r10_opr; break; + case objectTag: opr = FrameMap::r10_oop_opr; break; + case longTag: opr = FrameMap::long10_opr; break; + case floatTag: opr = FrameMap::fpu10_float_opr; break; + case doubleTag: opr = FrameMap::fpu10_double_opr; break; + + case addressTag: // fall through + default: + ShouldNotReachHere(); + return LIR_OprFact::illegalOpr; + } + + assert(opr->type_field() == as_OprType(as_BasicType(type)), "type mismatch"); + return opr; +} + + +LIR_Opr LIRGenerator::rlock_byte(BasicType type) { + LIR_Opr reg = new_register(T_INT); + set_vreg_flag(reg, LIRGenerator::byte_reg); + return reg; +} + +//--------- loading items into registers -------------------------------- + + +bool LIRGenerator::can_store_as_constant(Value v, BasicType type) const { + if (v->type()->as_IntConstant() != NULL) { + return v->type()->as_IntConstant()->value() == 0; + } else if (v->type()->as_LongConstant() != NULL) { + return v->type()->as_LongConstant()->value() == 0; + } else if (v->type()->as_ObjectConstant() != NULL) { + return v->type()->as_ObjectConstant()->value()->is_null_object(); + } else if (v->type()->as_FloatConstant() != NULL) { + return jint_cast(v->type()->as_FloatConstant()->value()) == 0.0f; + } else if (v->type()->as_DoubleConstant() != NULL) { + return jlong_cast(v->type()->as_DoubleConstant()->value()) == 0.0; + } + return false; +} + +bool LIRGenerator::can_inline_as_constant(Value v) const { + if (v->type()->as_IntConstant() != NULL) { + int value = v->type()->as_IntConstant()->value(); + // "-value" must be defined for value may be used for sub + return Assembler::operand_valid_for_add_immediate(value) && + Assembler::operand_valid_for_add_immediate(- value); + } else if (v->type()->as_ObjectConstant() != NULL) { + return v->type()->as_ObjectConstant()->value()->is_null_object(); + } else if (v->type()->as_LongConstant() != NULL) { + long value = v->type()->as_LongConstant()->value(); + // "-value" must be defined for value may be used for sub + return Assembler::operand_valid_for_add_immediate(value) && + Assembler::operand_valid_for_add_immediate(- value); + } else if (v->type()->as_FloatConstant() != NULL) { + return v->type()->as_FloatConstant()->value() == 0.0f; + } else if (v->type()->as_DoubleConstant() != NULL) { + return v->type()->as_DoubleConstant()->value() == 0.0; + } + return false; +} + +bool LIRGenerator::can_inline_as_constant(LIR_Const* c) const { + if (c->as_constant() != NULL) { + long constant = 0; + switch (c->type()) { + case T_INT: constant = c->as_jint(); break; + case T_LONG: constant = c->as_jlong(); break; + default: return false; + } + // "-constant" must be defined for c may be used for sub + return Assembler::operand_valid_for_add_immediate(constant) && + Assembler::operand_valid_for_add_immediate(- constant); + } + return false; +} + +LIR_Opr LIRGenerator::safepoint_poll_register() { + return LIR_OprFact::illegalOpr; +} + +LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, + int shift, int disp, BasicType type) { + assert(base->is_register(), "must be"); + + if (index->is_constant()) { + LIR_Const *constant = index->as_constant_ptr(); + jlong c; + if (constant->type() == T_INT) { + c = (jlong(index->as_jint()) << shift) + disp; + } else { + assert(constant->type() == T_LONG, "should be"); + c = (index->as_jlong() << shift) + disp; + } + if ((jlong)((jint)c) == c) { + return new LIR_Address(base, (jint)c, type); + } else { + LIR_Opr tmp = new_register(T_LONG); + __ move(index, tmp); + return new LIR_Address(base, tmp, type); + } + } + + return new LIR_Address(base, index, (LIR_Address::Scale)shift, disp, type); +} + +LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr, + BasicType type) { + int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type); + int elem_size = type2aelembytes(type); + int shift = exact_log2(elem_size); + return generate_address(array_opr, index_opr, shift, offset_in_bytes, type); +} + +LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) { + LIR_Opr r; + switch (type) { + case T_LONG: + r = LIR_OprFact::longConst(x); + break; + case T_INT: + r = LIR_OprFact::intConst(x); + break; + default: + ShouldNotReachHere(); + } + return r; +} + +void LIRGenerator::increment_counter(address counter, BasicType type, int step) { + LIR_Opr pointer = new_pointer_register(); + __ move(LIR_OprFact::intptrConst(counter), pointer); + LIR_Address* addr = new LIR_Address(pointer, type); + increment_counter(addr, step); +} + +void LIRGenerator::increment_counter(LIR_Address* addr, int step) { + LIR_Opr reg = new_register(addr->type()); + __ load(addr, reg); + __ add(reg, load_immediate(step, addr->type()), reg); + __ store(reg, addr); +} + +void LIRGenerator::cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info) { + LIR_Opr reg = new_register(T_INT); + __ load(generate_address(base, disp, T_INT), reg, info); + __ cmp(condition, reg, LIR_OprFact::intConst(c)); +} + +void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr base, int disp, BasicType type, CodeEmitInfo* info) { + LIR_Opr reg1 = new_register(T_INT); + __ load(generate_address(base, disp, type), reg1, info); + __ cmp(condition, reg, reg1); +} + +bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { + if (tmp->is_valid() && c > 0 && c < max_jint) { + if (is_power_of_2(c - 1)) { + __ shift_left(left, exact_log2(c - 1), tmp); + __ add(tmp, left, result); + return true; + } else if (is_power_of_2(c + 1)) { + __ shift_left(left, exact_log2(c + 1), tmp); + __ sub(tmp, left, result); + return true; + } + } + return false; +} + +void LIRGenerator::store_stack_parameter (LIR_Opr item, ByteSize offset_from_sp) { + BasicType type = item->type(); + __ store(item, new LIR_Address(FrameMap::sp_opr, in_bytes(offset_from_sp), type)); +} + +void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, + ciMethod* profiled_method, int profiled_bci) { + LIR_Opr tmp1 = new_register(objectType); + LIR_Opr tmp2 = new_register(objectType); + LIR_Opr tmp3 = new_register(objectType); + __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci); +} + +//---------------------------------------------------------------------- +// visitor functions +//---------------------------------------------------------------------- + +void LIRGenerator::do_MonitorEnter(MonitorEnter* x) { + assert(x->is_pinned(), ""); + LIRItem obj(x->obj(), this); + obj.load_item(); + + set_no_result(x); + + // "lock" stores the address of the monitor stack slot, so this is not an oop + LIR_Opr lock = new_register(T_INT); + + CodeEmitInfo* info_for_exception = NULL; + if (x->needs_null_check()) { + info_for_exception = state_for(x); + } + // this CodeEmitInfo must not have the xhandlers because here the + // object is already locked (xhandlers expect object to be unlocked) + CodeEmitInfo* info = state_for(x, x->state(), true); + monitor_enter(obj.result(), lock, syncTempOpr(), LIR_OprFact::illegalOpr, + x->monitor_no(), info_for_exception, info); +} + +void LIRGenerator::do_MonitorExit(MonitorExit* x) { + assert(x->is_pinned(), ""); + + LIRItem obj(x->obj(), this); + obj.dont_load_item(); + + LIR_Opr lock = new_register(T_INT); + LIR_Opr obj_temp = new_register(T_INT); + set_no_result(x); + monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no()); +} + +// neg +void LIRGenerator::do_NegateOp(NegateOp* x) { + LIRItem from(x->x(), this); + from.load_item(); + LIR_Opr result = rlock_result(x); + __ negate(from.result(), result); +} + +// for _fadd, _fmul, _fsub, _fdiv, _frem +// _dadd, _dmul, _dsub, _ddiv, _drem +void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + + if (x->op() == Bytecodes::_frem || x->op() == Bytecodes::_drem) { + + // float remainder is implemented as a direct call into the runtime + BasicTypeList signature(2); + if (x->op() == Bytecodes::_frem) { + signature.append(T_FLOAT); + signature.append(T_FLOAT); + } else { + signature.append(T_DOUBLE); + signature.append(T_DOUBLE); + } + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + + const LIR_Opr result_reg = result_register_for(x->type()); + + left.load_item(); + __ move(left.result(), cc->at(0)); + right.load_item_force(cc->at(1)); + + address entry; + if (x->op() == Bytecodes::_frem) { + entry = CAST_FROM_FN_PTR(address, SharedRuntime::frem); + } else { + entry = CAST_FROM_FN_PTR(address, SharedRuntime::drem); + } + + LIR_Opr result = rlock_result(x); + __ call_runtime_leaf(entry, getThreadTemp(), result_reg, cc->args()); + __ move(result_reg, result); + + return; + } + + if (!left.is_register()) { + left.load_item(); + } + // Always load right hand side. + right.load_item(); + + LIR_Opr reg = rlock(x); + arithmetic_op_fpu(x->op(), reg, left.result(), right.result()); + + set_result(x, round_item(reg)); +} + +// for _ladd, _lmul, _lsub, _ldiv, _lrem +void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { + + // missing test if instr is commutative and if we should swap + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + + if (x->op() == Bytecodes::_ldiv || x->op() == Bytecodes::_lrem) { + + left.load_item(); + + bool need_zero_check = true; + if (right.is_constant()) { + jlong c = right.get_jlong_constant(); + // no need to do div-by-zero check if the divisor is a non-zero constant + if (c != 0) { need_zero_check = false; } + // do not load right if the divisor is a power-of-2 constant + if (c > 0 && is_power_of_2(c)) { + right.dont_load_item(); + } else { + right.load_item(); + } + } else { + right.load_item(); + } + if (need_zero_check) { + CodeEmitInfo* info = state_for(x); + __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0)); + __ branch(lir_cond_equal, new DivByZeroStub(info)); + } + + rlock_result(x); + switch (x->op()) { + case Bytecodes::_lrem: + __ rem(left.result(), right.result(), x->operand()); + break; + case Bytecodes::_ldiv: + __ div(left.result(), right.result(), x->operand()); + break; + default: + ShouldNotReachHere(); + } + } else { + assert(x->op() == Bytecodes::_lmul || x->op() == Bytecodes::_ladd || x->op() == Bytecodes::_lsub, + "expect lmul, ladd or lsub"); + // add, sub, mul + left.load_item(); + if (!right.is_register()) { + if (x->op() == Bytecodes::_lmul || + !right.is_constant() || + (x->op() == Bytecodes::_ladd && + !Assembler::operand_valid_for_add_immediate(right.get_jlong_constant())) || + (x->op() == Bytecodes::_lsub && + !Assembler::operand_valid_for_add_immediate(-right.get_jlong_constant()))) { + right.load_item(); + } else { // add, sub + assert(x->op() == Bytecodes::_ladd || x->op() == Bytecodes::_lsub, "expected ladd or lsub"); + // don't load constants to save register + right.load_nonconstant(); + } + } + rlock_result(x); + arithmetic_op_long(x->op(), x->operand(), left.result(), right.result(), NULL); + } +} + +// for: _iadd, _imul, _isub, _idiv, _irem +void LIRGenerator::do_ArithmeticOp_Int(ArithmeticOp* x) { + + // Test if instr is commutative and if we should swap + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + LIRItem* left_arg = &left; + LIRItem* right_arg = &right; + if (x->is_commutative() && left.is_stack() && right.is_register()) { + // swap them if left is real stack (or cached) and right is real register(not cached) + left_arg = &right; + right_arg = &left; + } + left_arg->load_item(); + // do not need to load right, as we can handle stack and constants + if (x->op() == Bytecodes::_idiv || x->op() == Bytecodes::_irem) { + + rlock_result(x); + + bool need_zero_check = true; + if (right.is_constant()) { + jint c = right.get_jint_constant(); + // no need to do div-by-zero check if the divisor is a non-zero constant + if (c != 0) { need_zero_check = false; } + // do not load right if the divisor is a power-of-2 constant + if (c > 0 && is_power_of_2(c)) { + right_arg->dont_load_item(); + } else { + right_arg->load_item(); + } + } else { + right_arg->load_item(); + } + if (need_zero_check) { + CodeEmitInfo* info = state_for(x); + __ cmp(lir_cond_equal, right_arg->result(), LIR_OprFact::longConst(0)); + __ branch(lir_cond_equal, new DivByZeroStub(info)); + } + + LIR_Opr ill = LIR_OprFact::illegalOpr; + if (x->op() == Bytecodes::_irem) { + __ irem(left_arg->result(), right_arg->result(), x->operand(), ill, NULL); + } else if (x->op() == Bytecodes::_idiv) { + __ idiv(left_arg->result(), right_arg->result(), x->operand(), ill, NULL); + } + + } else if (x->op() == Bytecodes::_iadd || x->op() == Bytecodes::_isub) { + if (right.is_constant() && + ((x->op() == Bytecodes::_iadd && !Assembler::operand_valid_for_add_immediate(right.get_jint_constant())) || + (x->op() == Bytecodes::_isub && !Assembler::operand_valid_for_add_immediate(-right.get_jint_constant())))) { + right.load_nonconstant(); + } else { + right.load_item(); + } + rlock_result(x); + arithmetic_op_int(x->op(), x->operand(), left_arg->result(), right_arg->result(), LIR_OprFact::illegalOpr); + } else { + assert (x->op() == Bytecodes::_imul, "expect imul"); + if (right.is_constant()) { + jint c = right.get_jint_constant(); + if (c > 0 && c < max_jint && (is_power_of_2(c) || is_power_of_2(c - 1) || is_power_of_2(c + 1))) { + right_arg->dont_load_item(); + } else { + // Cannot use constant op. + right_arg->load_item(); + } + } else { + right.load_item(); + } + rlock_result(x); + arithmetic_op_int(x->op(), x->operand(), left_arg->result(), right_arg->result(), new_register(T_INT)); + } +} + +void LIRGenerator::do_ArithmeticOp(ArithmeticOp* x) { + // when an operand with use count 1 is the left operand, then it is + // likely that no move for 2-operand-LIR-form is necessary + if (x->is_commutative() && x->y()->as_Constant() == NULL && x->x()->use_count() > x->y()->use_count()) { + x->swap_operands(); + } + + ValueTag tag = x->type()->tag(); + assert(x->x()->type()->tag() == tag && x->y()->type()->tag() == tag, "wrong parameters"); + switch (tag) { + case floatTag: + case doubleTag: do_ArithmeticOp_FPU(x); return; + case longTag: do_ArithmeticOp_Long(x); return; + case intTag: do_ArithmeticOp_Int(x); return; + default: ShouldNotReachHere(); return; + } +} + +// _ishl, _lshl, _ishr, _lshr, _iushr, _lushr +void LIRGenerator::do_ShiftOp(ShiftOp* x) { + LIRItem value(x->x(), this); + LIRItem count(x->y(), this); + + value.load_item(); + if (count.is_constant()) { + assert(count.type()->as_IntConstant() != NULL || count.type()->as_LongConstant() != NULL , "should be"); + count.dont_load_item(); + } else { + count.load_item(); + } + + LIR_Opr res = rlock_result(x); + shift_op(x->op(), res, value.result(), count.result(), LIR_OprFact::illegalOpr); +} + + +// _iand, _land, _ior, _lor, _ixor, _lxor +void LIRGenerator::do_LogicOp(LogicOp* x) { + + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + + left.load_item(); + rlock_result(x); + ValueTag tag = right.type()->tag(); + if (right.is_constant() && + ((tag == longTag && Assembler::operand_valid_for_add_immediate(right.get_jlong_constant())) || + (tag == intTag && Assembler::operand_valid_for_add_immediate(right.get_jint_constant())))) { + right.dont_load_item(); + } else { + right.load_item(); + } + + switch (x->op()) { + case Bytecodes::_iand: // fall through + case Bytecodes::_land: + __ logical_and(left.result(), right.result(), x->operand()); break; + case Bytecodes::_ior: // fall through + case Bytecodes::_lor: + __ logical_or(left.result(), right.result(), x->operand()); break; + case Bytecodes::_ixor: // fall through + case Bytecodes::_lxor: + __ logical_xor(left.result(), right.result(), x->operand()); break; + default: Unimplemented(); + } +} + +// _lcmp, _fcmpl, _fcmpg, _dcmpl, _dcmpg +void LIRGenerator::do_CompareOp(CompareOp* x) { + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + ValueTag tag = x->x()->type()->tag(); + if (tag == longTag) { + left.set_destroys_register(); + } + left.load_item(); + right.load_item(); + LIR_Opr reg = rlock_result(x); + + if (x->x()->type()->is_float_kind()) { + Bytecodes::Code code = x->op(); + __ fcmp2int(left.result(), right.result(), reg, (code == Bytecodes::_fcmpl || code == Bytecodes::_dcmpl)); + } else if (x->x()->type()->tag() == longTag) { + __ lcmp2int(left.result(), right.result(), reg); + } else { + Unimplemented(); + } +} + +LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) { + LIR_Opr ill = LIR_OprFact::illegalOpr; // for convenience + new_value.load_item(); + cmp_value.load_item(); + LIR_Opr result = new_register(T_INT); + if (is_reference_type(type)) { + __ cas_obj(addr, cmp_value.result(), new_value.result(), new_register(T_INT), new_register(T_INT), result); + } else if (type == T_INT) { + __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill); + } else if (type == T_LONG) { + __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill); + } else { + ShouldNotReachHere(); + } + __ logical_xor(FrameMap::r5_opr, LIR_OprFact::intConst(1), result); + return result; +} + +LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) { + bool is_oop = is_reference_type(type); + LIR_Opr result = new_register(type); + value.load_item(); + assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type"); + LIR_Opr tmp = new_register(T_INT); + __ xchg(addr, value.result(), result, tmp); + return result; +} + +LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) { + LIR_Opr result = new_register(type); + value.load_item(); + assert(type == T_INT LP64_ONLY( || type == T_LONG ), "unexpected type"); + LIR_Opr tmp = new_register(T_INT); + __ xadd(addr, value.result(), result, tmp); + return result; +} + +void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { + assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), + "wrong type"); + + switch (x->id()) { + case vmIntrinsics::_dexp: // fall through + case vmIntrinsics::_dlog: // fall through + case vmIntrinsics::_dpow: // fall through + case vmIntrinsics::_dcos: // fall through + case vmIntrinsics::_dsin: // fall through + case vmIntrinsics::_dtan: // fall through + case vmIntrinsics::_dlog10: + do_LibmIntrinsic(x); + break; + case vmIntrinsics::_dabs: // fall through + case vmIntrinsics::_dsqrt: // fall through + case vmIntrinsics::_dsqrt_strict: { + assert(x->number_of_arguments() == 1, "wrong type"); + LIRItem value(x->argument_at(0), this); + value.load_item(); + LIR_Opr dst = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_dsqrt: // fall through + case vmIntrinsics::_dsqrt_strict: { + __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr); + break; + } + case vmIntrinsics::_dabs: { + __ abs(value.result(), dst, LIR_OprFact::illegalOpr); + break; + } + default: + ShouldNotReachHere(); + } + break; + } + default: + ShouldNotReachHere(); + } +} + +void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) { + LIRItem value(x->argument_at(0), this); + value.set_destroys_register(); + LIR_Opr calc_result = rlock_result(x); + LIR_Opr result_reg = result_register_for(x->type()); + CallingConvention* cc = NULL; + BasicTypeList signature(1); + signature.append(T_DOUBLE); + if (x->id() == vmIntrinsics::_dpow) { signature.append(T_DOUBLE); } + cc = frame_map()->c_calling_convention(&signature); + value.load_item_force(cc->at(0)); + if (x->id() == vmIntrinsics::_dpow) { + LIRItem value1(x->argument_at(1), this); + value1.set_destroys_register(); + value1.load_item_force(cc->at(1)); + } + switch (x->id()) { + case vmIntrinsics::_dexp: + if (StubRoutines::dexp() != NULL) { __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dlog: + if (StubRoutines::dlog() != NULL) { __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dlog10: + if (StubRoutines::dlog10() != NULL) { __ call_runtime_leaf(StubRoutines::dlog10(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dsin: + if (StubRoutines::dsin() != NULL) { __ call_runtime_leaf(StubRoutines::dsin(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dsin), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dcos: + if (StubRoutines::dcos() != NULL) { __ call_runtime_leaf(StubRoutines::dcos(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dcos), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dtan: + if (StubRoutines::dtan() != NULL) { __ call_runtime_leaf(StubRoutines::dtan(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), getThreadTemp(), result_reg, cc->args()); } + break; + case vmIntrinsics::_dpow: + if (StubRoutines::dpow() != NULL) { __ call_runtime_leaf(StubRoutines::dpow(), getThreadTemp(), result_reg, cc->args()); } + else { __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dpow), getThreadTemp(), result_reg, cc->args()); } + break; + default: ShouldNotReachHere(); + } + __ move(result_reg, calc_result); +} + + +void LIRGenerator::do_ArrayCopy(Intrinsic* x) { + assert(x->number_of_arguments() == 5, "wrong type"); + + // Make all state_for calls early since they can emit code + CodeEmitInfo* info = state_for(x, x->state()); + + LIRItem src(x->argument_at(0), this); + LIRItem src_pos(x->argument_at(1), this); + LIRItem dst(x->argument_at(2), this); + LIRItem dst_pos(x->argument_at(3), this); + LIRItem length(x->argument_at(4), this); + + // operands for arraycopy must use fixed registers, otherwise + // LinearScan will fail allocation (because arraycopy always needs a + // call) + + // The java calling convention will give us enough registers + // so that on the stub side the args will be perfect already. + // On the other slow/special case side we call C and the arg + // positions are not similar enough to pick one as the best. + // Also because the java calling convention is a "shifted" version + // of the C convention we can process the java args trivially into C + // args without worry of overwriting during the xfer + + src.load_item_force (FrameMap::as_oop_opr(j_rarg0)); + src_pos.load_item_force (FrameMap::as_opr(j_rarg1)); + dst.load_item_force (FrameMap::as_oop_opr(j_rarg2)); + dst_pos.load_item_force (FrameMap::as_opr(j_rarg3)); + length.load_item_force (FrameMap::as_opr(j_rarg4)); + + LIR_Opr tmp = FrameMap::as_opr(j_rarg5); + + set_no_result(x); + + int flags; + ciArrayKlass* expected_type = NULL; + arraycopy_helper(x, &flags, &expected_type); + + __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), tmp, + expected_type, flags, info); // does add_safepoint +} + +void LIRGenerator::do_update_CRC32(Intrinsic* x) { + ShouldNotReachHere(); +} + +void LIRGenerator::do_update_CRC32C(Intrinsic* x) { + ShouldNotReachHere(); +} + +void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { + assert(x->number_of_arguments() == 3, "wrong type"); + assert(UseFMA, "Needs FMA instructions support."); + LIRItem value(x->argument_at(0), this); + LIRItem value1(x->argument_at(1), this); + LIRItem value2(x->argument_at(2), this); + + value.load_item(); + value1.load_item(); + value2.load_item(); + + LIR_Opr calc_input = value.result(); + LIR_Opr calc_input1 = value1.result(); + LIR_Opr calc_input2 = value2.result(); + LIR_Opr calc_result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break; + case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break; + default: ShouldNotReachHere(); + } +} + +void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { + fatal("vectorizedMismatch intrinsic is not implemented on this platform"); +} + +// _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f +// _i2b, _i2c, _i2s +void LIRGenerator::do_Convert(Convert* x) { + LIRItem value(x->value(), this); + value.load_item(); + LIR_Opr input = value.result(); + LIR_Opr result = rlock(x); + + // arguments of lir_convert + LIR_Opr conv_input = input; + LIR_Opr conv_result = result; + + __ convert(x->op(), conv_input, conv_result); + + assert(result->is_virtual(), "result must be virtual register"); + set_result(x, result); +} + +void LIRGenerator::do_NewInstance(NewInstance* x) { +#ifndef PRODUCT + if (PrintNotLoaded && !x->klass()->is_loaded()) { + tty->print_cr(" ###class not loaded at new bci %d", x->printable_bci()); + } +#endif + CodeEmitInfo* info = state_for(x, x->state()); + LIR_Opr reg = result_register_for(x->type()); + new_instance(reg, x->klass(), x->is_unresolved(), + FrameMap::r12_oop_opr, + FrameMap::r15_oop_opr, + FrameMap::r14_oop_opr, + LIR_OprFact::illegalOpr, + FrameMap::r13_metadata_opr, + info); + LIR_Opr result = rlock_result(x); + __ move(reg, result); +} + +void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { + CodeEmitInfo* info = state_for(x, x->state()); + + LIRItem length(x->length(), this); + length.load_item_force(FrameMap::r9_opr); + + LIR_Opr reg = result_register_for(x->type()); + LIR_Opr tmp1 = FrameMap::r12_oop_opr; + LIR_Opr tmp2 = FrameMap::r14_oop_opr; + LIR_Opr tmp3 = FrameMap::r15_oop_opr; + LIR_Opr tmp4 = reg; + LIR_Opr klass_reg = FrameMap::r13_metadata_opr; + LIR_Opr len = length.result(); + BasicType elem_type = x->elt_type(); + + __ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); + + CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); + __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path); + + LIR_Opr result = rlock_result(x); + __ move(reg, result); +} + +void LIRGenerator::do_NewObjectArray(NewObjectArray* x) { + LIRItem length(x->length(), this); + // in case of patching (i.e., object class is not yet loaded), we need to reexecute the instruction + // and therefore provide the state before the parameters have been consumed + CodeEmitInfo* patching_info = NULL; + if (!x->klass()->is_loaded() || PatchALot) { + patching_info = state_for(x, x->state_before()); + } + + CodeEmitInfo* info = state_for(x, x->state()); + + LIR_Opr reg = result_register_for(x->type()); + LIR_Opr tmp1 = FrameMap::r12_oop_opr; + LIR_Opr tmp2 = FrameMap::r14_oop_opr; + LIR_Opr tmp3 = FrameMap::r15_oop_opr; + LIR_Opr tmp4 = reg; + LIR_Opr klass_reg = FrameMap::r13_metadata_opr; + + length.load_item_force(FrameMap::r9_opr); + LIR_Opr len = length.result(); + + CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info); + ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass()); + if (obj == ciEnv::unloaded_ciobjarrayklass()) { + BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error"); + } + klass2reg_with_patching(klass_reg, obj, patching_info); + __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, T_OBJECT, klass_reg, slow_path); + + LIR_Opr result = rlock_result(x); + __ move(reg, result); +} + + +void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { + Values* dims = x->dims(); + int i = dims->length(); + LIRItemList* items = new LIRItemList(i, i, NULL); + while (i-- > 0) { + LIRItem* size = new LIRItem(dims->at(i), this); + items->at_put(i, size); + } + + // Evaluate state_for early since it may emit code. + CodeEmitInfo* patching_info = NULL; + if (!x->klass()->is_loaded() || PatchALot) { + patching_info = state_for(x, x->state_before()); + + // Cannot re-use same xhandlers for multiple CodeEmitInfos, so + // clone all handlers (NOTE: Usually this is handled transparently + // by the CodeEmitInfo cloning logic in CodeStub constructors but + // is done explicitly here because a stub isn't being used). + x->set_exception_handlers(new XHandlers(x->exception_handlers())); + } + CodeEmitInfo* info = state_for(x, x->state()); + + i = dims->length(); + while (i-- > 0) { + LIRItem* size = items->at(i); + size->load_item(); + + store_stack_parameter(size->result(), in_ByteSize(i * BytesPerInt)); + } + + LIR_Opr klass_reg = FrameMap::r10_metadata_opr; + klass2reg_with_patching(klass_reg, x->klass(), patching_info); + + LIR_Opr rank = FrameMap::r9_opr; + __ move(LIR_OprFact::intConst(x->rank()), rank); + LIR_Opr varargs = FrameMap::r12_opr; + __ move(FrameMap::sp_opr, varargs); + LIR_OprList* args = new LIR_OprList(3); + args->append(klass_reg); + args->append(rank); + args->append(varargs); + LIR_Opr reg = result_register_for(x->type()); + __ call_runtime(Runtime1::entry_for(Runtime1::new_multi_array_id), + LIR_OprFact::illegalOpr, + reg, args, info); + + LIR_Opr result = rlock_result(x); + __ move(reg, result); +} + +void LIRGenerator::do_BlockBegin(BlockBegin* x) { + // nothing to do for now +} + +void LIRGenerator::do_CheckCast(CheckCast* x) { + LIRItem obj(x->obj(), this); + + CodeEmitInfo* patching_info = NULL; + if (!x->klass()->is_loaded() || + (PatchALot && !x->is_incompatible_class_change_check() && !x->is_invokespecial_receiver_check())) { + // must do this before locking the destination register as an oop register, + // and before the obj is loaded (the latter is for deoptimization) + patching_info = state_for(x, x->state_before()); + } + obj.load_item(); + + // info for exceptions + CodeEmitInfo* info_for_exception = + (x->needs_exception_state() ? state_for(x) : + state_for(x, x->state_before(), true /*ignore_xhandler*/ )); + + CodeStub* stub = NULL; + if (x->is_incompatible_class_change_check()) { + assert(patching_info == NULL, "can't patch this"); + stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, + info_for_exception); + } else if (x->is_invokespecial_receiver_check()) { + assert(patching_info == NULL, "can't patch this"); + stub = new DeoptimizeStub(info_for_exception, + Deoptimization::Reason_class_check, + Deoptimization::Action_none); + } else { + stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception); + } + LIR_Opr reg = rlock_result(x); + LIR_Opr tmp3 = LIR_OprFact::illegalOpr; + if (!x->klass()->is_loaded() || UseCompressedClassPointers) { + tmp3 = new_register(objectType); + } + __ checkcast(reg, obj.result(), x->klass(), + new_register(objectType), new_register(objectType), tmp3, + x->direct_compare(), info_for_exception, patching_info, stub, + x->profiled_method(), x->profiled_bci()); +} + +void LIRGenerator::do_InstanceOf(InstanceOf* x) { + LIRItem obj(x->obj(), this); + + // result and test object may not be in same register + LIR_Opr reg = rlock_result(x); + CodeEmitInfo* patching_info = NULL; + if ((!x->klass()->is_loaded() || PatchALot)) { + // must do this before locking the destination register as an oop register + patching_info = state_for(x, x->state_before()); + } + obj.load_item(); + LIR_Opr tmp3 = LIR_OprFact::illegalOpr; + if (!x->klass()->is_loaded() || UseCompressedClassPointers) { + tmp3 = new_register(objectType); + } + __ instanceof(reg, obj.result(), x->klass(), + new_register(objectType), new_register(objectType), tmp3, + x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); +} + +void LIRGenerator::do_If(If* x) { + // If should have two successors + assert(x->number_of_sux() == 2, "inconsistency"); + ValueTag tag = x->x()->type()->tag(); + bool is_safepoint = x->is_safepoint(); + + If::Condition cond = x->cond(); + + LIRItem xitem(x->x(), this); + LIRItem yitem(x->y(), this); + LIRItem* xin = &xitem; + LIRItem* yin = &yitem; + + if (tag == longTag) { + // for longs, only conditions "eql", "neq", "lss", "geq" are valid; + // mirror for other conditions + if (cond == If::gtr || cond == If::leq) { + cond = Instruction::mirror(cond); + xin = &yitem; + yin = &xitem; + } + xin->set_destroys_register(); + } + xin->load_item(); + yin->load_item(); + + set_no_result(x); + + LIR_Opr left = xin->result(); + LIR_Opr right = yin->result(); + + // add safepoint before generating condition code so it can be recomputed + if (x->is_safepoint()) { + // increment backedge counter if needed + increment_backedge_counter_conditionally(lir_cond(cond), left, right, state_for(x, x->state_before()), + x->tsux()->bci(), x->fsux()->bci(), x->profiled_bci()); + __ safepoint(LIR_OprFact::illegalOpr, state_for(x, x->state_before())); + } + + // Generate branch profiling. Profiling code doesn't kill flags. + __ cmp(lir_cond(cond), left, right); + profile_branch(x, cond); + move_to_phi(x->state()); + if (x->x()->type()->is_float_kind()) { + __ branch(lir_cond(cond), x->tsux(), x->usux()); + } else { + __ branch(lir_cond(cond), x->tsux()); + } + assert(x->default_sux() == x->fsux(), "wrong destination above"); + __ jump(x->default_sux()); +} + +LIR_Opr LIRGenerator::getThreadPointer() { + return FrameMap::as_pointer_opr(xthread); +} + +void LIRGenerator::trace_block_entry(BlockBegin* block) { Unimplemented(); } + +void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address, + CodeEmitInfo* info) { + __ volatile_store_mem_reg(value, address, info); +} + +void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result, + CodeEmitInfo* info) { + __ volatile_load_mem_reg(address, result, info); +} diff --git a/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f1c394ab3d465a7d2e1989d0553d45281ad5994 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/register.hpp" +#include "c1/c1_LIR.hpp" + +FloatRegister LIR_Opr::as_float_reg() const { + return as_FloatRegister(fpu_regnr()); +} + +FloatRegister LIR_Opr::as_double_reg() const { + return as_FloatRegister(fpu_regnrLo()); +} + +// Reg2 unused. +LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { + assert(as_FloatRegister(reg2) == fnoreg, "Not used on this platform"); + return (LIR_Opr)(intptr_t)((reg1 << LIR_Opr::reg1_shift) | + (reg1 << LIR_Opr::reg2_shift) | + LIR_Opr::double_type | + LIR_Opr::fpu_register | + LIR_Opr::double_size); +} + +#ifndef PRODUCT +void LIR_Address::verify() const { + assert(base()->is_cpu_register(), "wrong base operand"); + assert(index()->is_illegal() || index()->is_double_cpu() || index()->is_single_cpu(), "wrong index operand"); + assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || + base()->type() == T_METADATA, "wrong type for addresses"); +} +#endif // PRODUCT diff --git a/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78a61128bdd5ddd9175c5aaa340d1d5e0f654a8c --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_Instruction.hpp" +#include "c1/c1_LinearScan.hpp" +#include "utilities/bitMap.inline.hpp" + +void LinearScan::allocate_fpu_stack() { + // No FPU stack on RISCV +} diff --git a/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d7ca7b0fd052434d409666a7bcf45fc70c5c191c --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_LINEARSCAN_RISCV_HPP +#define CPU_RISCV_C1_LINEARSCAN_RISCV_HPP + +inline bool LinearScan::is_processed_reg_num(int reg_num) +{ + return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map; +} + +inline int LinearScan::num_physical_regs(BasicType type) { + return 1; +} + +inline bool LinearScan::requires_adjacent_regs(BasicType type) { + return false; +} + +inline bool LinearScan::is_caller_save(int assigned_reg) { + assert(assigned_reg >= 0 && assigned_reg < nof_regs, "should call this only for registers"); + if (assigned_reg < pd_first_callee_saved_reg) { + return true; + } + if (assigned_reg > pd_last_callee_saved_reg && assigned_reg < pd_first_callee_saved_fpu_reg_1) { + return true; + } + if (assigned_reg > pd_last_callee_saved_fpu_reg_1 && assigned_reg < pd_first_callee_saved_fpu_reg_2) { + return true; + } + if (assigned_reg > pd_last_callee_saved_fpu_reg_2 && assigned_reg < pd_last_fpu_reg) { + return true; + } + return false; +} + +inline void LinearScan::pd_add_temps(LIR_Op* op) { + // No special case behaviours yet +} + + +// Implementation of LinearScanWalker + +inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) +{ + if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::callee_saved)) { + assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); + _first_reg = pd_first_callee_saved_reg; + _last_reg = pd_last_callee_saved_reg; + return true; + } else if (cur->type() == T_INT || cur->type() == T_LONG || cur->type() == T_OBJECT || + cur->type() == T_ADDRESS || cur->type() == T_METADATA) { + _first_reg = pd_first_cpu_reg; + _last_reg = pd_last_allocatable_cpu_reg; + return true; + } + return false; +} + +#endif // CPU_RISCV_C1_LINEARSCAN_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f656c8c533481fafa627c3c34d24031b70f089f --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -0,0 +1,432 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_LIR.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "c1/c1_Runtime1.hpp" +#include "classfile/systemDictionary.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interpreter.hpp" +#include "oops/arrayOop.hpp" +#include "oops/markWord.hpp" +#include "runtime/basicLock.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" + +void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result, + FloatRegister freg0, FloatRegister freg1, + Register result) +{ + if (is_float) { + float_compare(result, freg0, freg1, unordered_result); + } else { + double_compare(result, freg0, freg1, unordered_result); + } +} + +int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) { + const int aligned_mask = BytesPerWord - 1; + const int hdr_offset = oopDesc::mark_offset_in_bytes(); + assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); + Label done; + int null_check_offset = -1; + + verify_oop(obj); + + // save object being locked into the BasicObjectLock + sd(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); + + null_check_offset = offset(); + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(hdr, obj); + lwu(hdr, Address(hdr, Klass::access_flags_offset())); + andi(t0, hdr, JVM_ACC_IS_VALUE_BASED_CLASS); + bnez(t0, slow_case, true /* is_far */); + } + + // Load object header + ld(hdr, Address(obj, hdr_offset)); + // and mark it as unlocked + ori(hdr, hdr, markWord::unlocked_value); + // save unlocked object header into the displaced header location on the stack + sd(hdr, Address(disp_hdr, 0)); + // test if object header is still the same (i.e. unlocked), and if so, store the + // displaced header address in the object header - if it is not the same, get the + // object header instead + la(t1, Address(obj, hdr_offset)); + cmpxchgptr(hdr, disp_hdr, t1, t0, done, /*fallthough*/NULL); + // if the object header was the same, we're done + // if the object header was not the same, it is now in the hdr register + // => test if it is a stack pointer into the same stack (recursive locking), i.e.: + // + // 1) (hdr & aligned_mask) == 0 + // 2) sp <= hdr + // 3) hdr <= sp + page_size + // + // these 3 tests can be done by evaluating the following expression: + // + // (hdr -sp) & (aligned_mask - page_size) + // + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + sub(hdr, hdr, sp); + li(t0, aligned_mask - os::vm_page_size()); + andr(hdr, hdr, t0); + // for recursive locking, the result is zero => save it in the displaced header + // location (NULL in the displaced hdr location indicates recursive locking) + sd(hdr, Address(disp_hdr, 0)); + // otherwise we don't care about the result and handle locking via runtime call + bnez(hdr, slow_case, /* is_far */ true); + bind(done); + return null_check_offset; +} + +void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) { + const int aligned_mask = BytesPerWord - 1; + const int hdr_offset = oopDesc::mark_offset_in_bytes(); + assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); + Label done; + + // load displaced header + ld(hdr, Address(disp_hdr, 0)); + // if the loaded hdr is NULL we had recursive locking + // if we had recursive locking, we are done + beqz(hdr, done); + // load object + ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); + verify_oop(obj); + // test if object header is pointing to the displaced header, and if so, restore + // the displaced header in the object - if the object header is not pointing to + // the displaced header, get the object header instead + // if the object header was not pointing to the displaced header, + // we do unlocking via runtime call + if (hdr_offset) { + la(t0, Address(obj, hdr_offset)); + cmpxchgptr(disp_hdr, hdr, t0, t1, done, &slow_case); + } else { + cmpxchgptr(disp_hdr, hdr, obj, t1, done, &slow_case); + } + bind(done); +} + +// Defines obj, preserves var_size_in_bytes +void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register tmp1, Register tmp2, Label& slow_case) { + if (UseTLAB) { + tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, tmp1, tmp2, slow_case, /* is_far */ true); + } else { + eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, tmp1, slow_case, /* is_far */ true); + } +} + +void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register tmp1, Register tmp2) { + assert_different_registers(obj, klass, len); + // This assumes that all prototype bits fitr in an int32_t + mv(tmp1, (int32_t)(intptr_t)markWord::prototype().value()); + sd(tmp1, Address(obj, oopDesc::mark_offset_in_bytes())); + + if (UseCompressedClassPointers) { // Take care not to kill klass + encode_klass_not_null(tmp1, klass); + sw(tmp1, Address(obj, oopDesc::klass_offset_in_bytes())); + } else { + sd(klass, Address(obj, oopDesc::klass_offset_in_bytes())); + } + + if (len->is_valid()) { + sw(len, Address(obj, arrayOopDesc::length_offset_in_bytes())); + } else if (UseCompressedClassPointers) { + store_klass_gap(obj, zr); + } +} + +// preserves obj, destroys len_in_bytes +void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register tmp) { + assert(hdr_size_in_bytes >= 0, "header size must be positive or 0"); + Label done; + + // len_in_bytes is positive and ptr sized + sub(len_in_bytes, len_in_bytes, hdr_size_in_bytes); + beqz(len_in_bytes, done); + + // Preserve obj + if (hdr_size_in_bytes) { + add(obj, obj, hdr_size_in_bytes); + } + zero_memory(obj, len_in_bytes, tmp); + if (hdr_size_in_bytes) { + sub(obj, obj, hdr_size_in_bytes); + } + + bind(done); +} + +void C1_MacroAssembler::allocate_object(Register obj, Register tmp1, Register tmp2, int header_size, int object_size, Register klass, Label& slow_case) { + assert_different_registers(obj, tmp1, tmp2); + assert(header_size >= 0 && object_size >= header_size, "illegal sizes"); + + try_allocate(obj, noreg, object_size * BytesPerWord, tmp1, tmp2, slow_case); + + initialize_object(obj, klass, noreg, object_size * HeapWordSize, tmp1, tmp2, UseTLAB); +} + +void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register tmp1, Register tmp2, bool is_tlab_allocated) { + assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, + "con_size_in_bytes is not multiple of alignment"); + const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; + + initialize_header(obj, klass, noreg, tmp1, tmp2); + + if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) { + // clear rest of allocated space + const Register index = tmp2; + // 16: multipler for threshold + const int threshold = 16 * BytesPerWord; // approximate break even point for code size (see comments below) + if (var_size_in_bytes != noreg) { + mv(index, var_size_in_bytes); + initialize_body(obj, index, hdr_size_in_bytes, tmp1); + } else if (con_size_in_bytes <= threshold) { + // use explicit null stores + int i = hdr_size_in_bytes; + if (i < con_size_in_bytes && (con_size_in_bytes % (2 * BytesPerWord))) { // 2: multipler for BytesPerWord + sd(zr, Address(obj, i)); + i += BytesPerWord; + } + for (; i < con_size_in_bytes; i += BytesPerWord) { + sd(zr, Address(obj, i)); + } + } else if (con_size_in_bytes > hdr_size_in_bytes) { + block_comment("zero memory"); + // use loop to null out the fields + int words = (con_size_in_bytes - hdr_size_in_bytes) / BytesPerWord; + mv(index, words / 8); // 8: byte size + + const int unroll = 8; // Number of sd(zr) instructions we'll unroll + int remainder = words % unroll; + la(t0, Address(obj, hdr_size_in_bytes + remainder * BytesPerWord)); + + Label entry_point, loop; + j(entry_point); + + bind(loop); + sub(index, index, 1); + for (int i = -unroll; i < 0; i++) { + if (-i == remainder) { + bind(entry_point); + } + sd(zr, Address(t0, i * wordSize)); + } + if (remainder == 0) { + bind(entry_point); + } + add(t0, t0, unroll * wordSize); + bnez(index, loop); + } + } + + membar(MacroAssembler::StoreStore); + + if (CURRENT_ENV->dtrace_alloc_probes()) { + assert(obj == x10, "must be"); + far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id))); + } + + verify_oop(obj); +} + +void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case) { + assert_different_registers(obj, len, tmp1, tmp2, klass); + + // determine alignment mask + assert(!(BytesPerWord & 1), "must be multiple of 2 for masking code to work"); + + // check for negative or excessive length + mv(t0, (int32_t)max_array_allocation_length); + bgeu(len, t0, slow_case, /* is_far */ true); + + const Register arr_size = tmp2; // okay to be the same + // align object end + mv(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask); + shadd(arr_size, len, arr_size, t0, f); + andi(arr_size, arr_size, ~(uint)MinObjAlignmentInBytesMask); + + try_allocate(obj, arr_size, 0, tmp1, tmp2, slow_case); + + initialize_header(obj, klass, len, tmp1, tmp2); + + // clear rest of allocated space + const Register len_zero = len; + initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero); + + membar(MacroAssembler::StoreStore); + + if (CURRENT_ENV->dtrace_alloc_probes()) { + assert(obj == x10, "must be"); + far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id))); + } + + verify_oop(obj); +} + +void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache, Label &L) { + verify_oop(receiver); + // explicit NULL check not needed since load from [klass_offset] causes a trap + // check against inline cache + assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); + cmp_klass(receiver, iCache, t0, L); +} + +void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { + assert(bang_size_in_bytes >= framesize, "stack bang size incorrect"); + // Make sure there is enough stack space for this method's activation. + // Note that we do this before creating a frame. + generate_stack_overflow_check(bang_size_in_bytes); + MacroAssembler::build_frame(framesize); + + // Insert nmethod entry barrier into frame. + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(this); +} + +void C1_MacroAssembler::remove_frame(int framesize) { + MacroAssembler::remove_frame(framesize); +} + + +void C1_MacroAssembler::verified_entry(bool breakAtEntry) { + // If we have to make this method not-entrant we'll overwrite its + // first instruction with a jump. For this action to be legal we + // must ensure that this first instruction is a J, JAL or NOP. + // Make it a NOP. + + nop(); +} + +void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) { + // fp + -2: link + // + -1: return address + // + 0: argument with offset 0 + // + 1: argument with offset 1 + // + 2: ... + ld(reg, Address(fp, offset_in_words * BytesPerWord)); +} + +#ifndef PRODUCT + +void C1_MacroAssembler::verify_stack_oop(int stack_offset) { + if (!VerifyOops) { + return; + } + verify_oop_addr(Address(sp, stack_offset), "oop"); +} + +void C1_MacroAssembler::verify_not_null_oop(Register r) { + if (!VerifyOops) return; + Label not_null; + bnez(r, not_null); + stop("non-null oop required"); + bind(not_null); + verify_oop(r); +} + +void C1_MacroAssembler::invalidate_registers(bool inv_x10, bool inv_x9, bool inv_x12, bool inv_x13, bool inv_x14, bool inv_x15) { +#ifdef ASSERT + static int nn; + if (inv_x10) { mv(x10, 0xDEAD); } + if (inv_x9) { mv(x9, 0xDEAD); } + if (inv_x12) { mv(x12, nn++); } + if (inv_x13) { mv(x13, 0xDEAD); } + if (inv_x14) { mv(x14, 0xDEAD); } + if (inv_x15) { mv(x15, 0xDEAD); } +#endif // ASSERT +} +#endif // ifndef PRODUCT + +typedef void (C1_MacroAssembler::*c1_cond_branch_insn)(Register op1, Register op2, Label& label, bool is_far); +typedef void (C1_MacroAssembler::*c1_float_cond_branch_insn)(FloatRegister op1, FloatRegister op2, + Label& label, bool is_far, bool is_unordered); + +static c1_cond_branch_insn c1_cond_branch[] = +{ + /* SHORT branches */ + (c1_cond_branch_insn)&Assembler::beq, + (c1_cond_branch_insn)&Assembler::bne, + (c1_cond_branch_insn)&Assembler::blt, + (c1_cond_branch_insn)&Assembler::ble, + (c1_cond_branch_insn)&Assembler::bge, + (c1_cond_branch_insn)&Assembler::bgt, + (c1_cond_branch_insn)&Assembler::bleu, // lir_cond_belowEqual + (c1_cond_branch_insn)&Assembler::bgeu // lir_cond_aboveEqual +}; + +static c1_float_cond_branch_insn c1_float_cond_branch[] = +{ + /* FLOAT branches */ + (c1_float_cond_branch_insn)&MacroAssembler::float_beq, + (c1_float_cond_branch_insn)&MacroAssembler::float_bne, + (c1_float_cond_branch_insn)&MacroAssembler::float_blt, + (c1_float_cond_branch_insn)&MacroAssembler::float_ble, + (c1_float_cond_branch_insn)&MacroAssembler::float_bge, + (c1_float_cond_branch_insn)&MacroAssembler::float_bgt, + NULL, // lir_cond_belowEqual + NULL, // lir_cond_aboveEqual + + /* DOUBLE branches */ + (c1_float_cond_branch_insn)&MacroAssembler::double_beq, + (c1_float_cond_branch_insn)&MacroAssembler::double_bne, + (c1_float_cond_branch_insn)&MacroAssembler::double_blt, + (c1_float_cond_branch_insn)&MacroAssembler::double_ble, + (c1_float_cond_branch_insn)&MacroAssembler::double_bge, + (c1_float_cond_branch_insn)&MacroAssembler::double_bgt, + NULL, // lir_cond_belowEqual + NULL // lir_cond_aboveEqual +}; + +void C1_MacroAssembler::c1_cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, + BasicType type, bool is_far) { + if (type == T_OBJECT || type == T_ARRAY) { + assert(cmpFlag == lir_cond_equal || cmpFlag == lir_cond_notEqual, "Should be equal or notEqual"); + if (cmpFlag == lir_cond_equal) { + beq(op1, op2, label, is_far); + } else { + bne(op1, op2, label, is_far); + } + } else { + assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(c1_cond_branch) / sizeof(c1_cond_branch[0])), + "invalid c1 conditional branch index"); + (this->*c1_cond_branch[cmpFlag])(op1, op2, label, is_far); + } +} + +void C1_MacroAssembler::c1_float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, + bool is_far, bool is_unordered) { + assert(cmpFlag >= 0 && + cmpFlag < (int)(sizeof(c1_float_cond_branch) / sizeof(c1_float_cond_branch[0])), + "invalid c1 float conditional branch index"); + (this->*c1_float_cond_branch[cmpFlag])(op1, op2, label, is_far, is_unordered); +} diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dfd3c17d7c79b8ee745dda2fb768ba430be100d3 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_MACROASSEMBLER_RISCV_HPP +#define CPU_RISCV_C1_MACROASSEMBLER_RISCV_HPP + +using MacroAssembler::build_frame; +using MacroAssembler::null_check; + +// C1_MacroAssembler contains high-level macros for C1 + + private: + int _rsp_offset; // track rsp changes + // initialization + void pd_init() { _rsp_offset = 0; } + + + public: + void try_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + + void initialize_header(Register obj, Register klass, Register len, Register tmp1, Register tmp2); + void initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register tmp); + + void float_cmp(bool is_float, int unordered_result, + FloatRegister f0, FloatRegister f1, + Register result); + + // locking + // hdr : must be x10, contents destroyed + // obj : must point to the object to lock, contents preserved + // disp_hdr: must point to the displaced header location, contents preserved + // returns code offset at which to add null check debug information + int lock_object (Register swap, Register obj, Register disp_hdr, Label& slow_case); + + // unlocking + // hdr : contents destroyed + // obj : must point to the object to lock, contents preserved + // disp_hdr: must be x10 & must point to the displaced header location, contents destroyed + void unlock_object(Register swap, Register obj, Register lock, Label& slow_case); + + void initialize_object( + Register obj, // result: pointer to object after successful allocation + Register klass, // object klass + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + bool is_tlab_allocated // the object was allocated in a TLAB; relevant for the implementation of ZeroTLAB + ); + + // allocation of fixed-size objects + // (can also be used to allocate fixed-size arrays, by setting + // hdr_size correctly and storing the array length afterwards) + // obj : will contain pointer to allocated object + // t1, t2 : temp registers - contents destroyed + // header_size: size of object header in words + // object_size: total size of object in words + // slow_case : exit to slow case implementation if fast allocation fails + void allocate_object(Register obj, Register tmp1, Register tmp2, int header_size, int object_size, Register klass, Label& slow_case); + + enum { + max_array_allocation_length = 0x00FFFFFF + }; + + // allocation of arrays + // obj : will contain pointer to allocated object + // len : array length in number of elements + // t : temp register - contents destroyed + // header_size: size of object header in words + // f : element scale factor + // slow_case : exit to slow case implementation if fast allocation fails + void allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case); + + int rsp_offset() const { return _rsp_offset; } + + void invalidate_registers(bool inv_r0, bool inv_r19, bool inv_r2, bool inv_r3, bool inv_r4, bool inv_r5) PRODUCT_RETURN; + + // This platform only uses signal-based null checks. The Label is not needed. + void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); } + + void load_parameter(int offset_in_words, Register reg); + + void inline_cache_check(Register receiver, Register iCache, Label &L); + + static const int c1_double_branch_mask = 1 << 3; // depend on c1_float_cond_branch + void c1_cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, BasicType type, bool is_far); + void c1_float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, + bool is_far, bool is_unordered = false); + +#endif // CPU_RISCV_C1_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f523c9ed50a6fc5d1defd4ce4202f32932f32c0a --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "c1/c1_CodeStubs.hpp" +#include "c1/c1_Defs.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "c1/c1_Runtime1.hpp" +#include "compiler/disassembler.hpp" +#include "compiler/oopMap.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/cardTableBarrierSet.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/universe.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/compiledICHolder.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "register_riscv.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/signature.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/vframe.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + + +// Implementation of StubAssembler + +int StubAssembler::call_RT(Register oop_result, Register metadata_result, address entry, int args_size) { + // setup registers + assert(!(oop_result->is_valid() || metadata_result->is_valid()) || oop_result != metadata_result, + "registers must be different"); + assert(oop_result != xthread && metadata_result != xthread, "registers must be different"); + assert(args_size >= 0, "illegal args_size"); + bool align_stack = false; + + mv(c_rarg0, xthread); + set_num_rt_args(0); // Nothing on stack + + Label retaddr; + set_last_Java_frame(sp, fp, retaddr, t0); + + // do the call + int32_t off = 0; + la_patchable(t0, RuntimeAddress(entry), off); + jalr(x1, t0, off); + bind(retaddr); + int call_offset = offset(); + // verify callee-saved register +#ifdef ASSERT + push_reg(x10, sp); + { Label L; + get_thread(x10); + beq(xthread, x10, L); + stop("StubAssembler::call_RT: xthread not callee saved?"); + bind(L); + } + pop_reg(x10, sp); +#endif + reset_last_Java_frame(true); + + // check for pending exceptions + { Label L; + // check for pending exceptions (java_thread is set upon return) + ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + beqz(t0, L); + // exception pending => remove activation and forward to exception handler + // make sure that the vm_results are cleared + if (oop_result->is_valid()) { + sd(zr, Address(xthread, JavaThread::vm_result_offset())); + } + if (metadata_result->is_valid()) { + sd(zr, Address(xthread, JavaThread::vm_result_2_offset())); + } + if (frame_size() == no_frame_size) { + leave(); + far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + } else if (_stub_id == Runtime1::forward_exception_id) { + should_not_reach_here(); + } else { + far_jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); + } + bind(L); + } + // get oop results if there are any and reset the values in the thread + if (oop_result->is_valid()) { + get_vm_result(oop_result, xthread); + } + if (metadata_result->is_valid()) { + get_vm_result_2(metadata_result, xthread); + } + return call_offset; +} + +int StubAssembler::call_RT(Register oop_result, Register metadata_result, address entry, Register arg1) { + mv(c_rarg1, arg1); + return call_RT(oop_result, metadata_result, entry, 1); +} + +int StubAssembler::call_RT(Register oop_result, Register metadata_result, address entry, Register arg1, Register arg2) { + const int arg_num = 2; + if (c_rarg1 == arg2) { + if (c_rarg2 == arg1) { + xorr(arg1, arg1, arg2); + xorr(arg2, arg1, arg2); + xorr(arg1, arg1, arg2); + } else { + mv(c_rarg2, arg2); + mv(c_rarg1, arg1); + } + } else { + mv(c_rarg1, arg1); + mv(c_rarg2, arg2); + } + return call_RT(oop_result, metadata_result, entry, arg_num); +} + +int StubAssembler::call_RT(Register oop_result, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3) { + const int arg_num = 3; + // if there is any conflict use the stack + if (arg1 == c_rarg2 || arg1 == c_rarg3 || + arg2 == c_rarg1 || arg2 == c_rarg3 || + arg3 == c_rarg1 || arg3 == c_rarg2) { + const int arg1_sp_offset = 0; + const int arg2_sp_offset = 1; + const int arg3_sp_offset = 2; + addi(sp, sp, -(arg_num + 1) * wordSize); + sd(arg1, Address(sp, arg1_sp_offset * wordSize)); + sd(arg2, Address(sp, arg2_sp_offset * wordSize)); + sd(arg3, Address(sp, arg3_sp_offset * wordSize)); + + ld(c_rarg1, Address(sp, arg1_sp_offset * wordSize)); + ld(c_rarg2, Address(sp, arg2_sp_offset * wordSize)); + ld(c_rarg3, Address(sp, arg3_sp_offset * wordSize)); + addi(sp, sp, (arg_num + 1) * wordSize); + } else { + mv(c_rarg1, arg1); + mv(c_rarg2, arg2); + mv(c_rarg3, arg3); + } + return call_RT(oop_result, metadata_result, entry, arg_num); +} + +enum return_state_t { + does_not_return, requires_return +}; + +// Implementation of StubFrame + +class StubFrame: public StackObj { + private: + StubAssembler* _sasm; + bool _return_state; + + public: + StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state=requires_return); + void load_argument(int offset_in_words, Register reg); + + ~StubFrame(); +};; + +void StubAssembler::prologue(const char* name, bool must_gc_arguments) { + set_info(name, must_gc_arguments); + enter(); +} + +void StubAssembler::epilogue() { + leave(); + ret(); +} + +#define __ _sasm-> + +StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state) { + _sasm = sasm; + _return_state = return_state; + __ prologue(name, must_gc_arguments); +} + +// load parameters that were stored with LIR_Assembler::store_parameter +// Note: offsets for store_parameter and load_argument must match +void StubFrame::load_argument(int offset_in_words, Register reg) { + __ load_parameter(offset_in_words, reg); +} + + +StubFrame::~StubFrame() { + if (_return_state == requires_return) { + __ epilogue(); + } else { + __ should_not_reach_here(); + } + _sasm = NULL; +} + +#undef __ + + +// Implementation of Runtime1 + +#define __ sasm-> + +const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; + +// Stack layout for saving/restoring all the registers needed during a runtime +// call (this includes deoptimization) +// Note: note that users of this frame may well have arguments to some runtime +// while these values are on the stack. These positions neglect those arguments +// but the code in save_live_registers will take the argument count into +// account. +// + +enum reg_save_layout { + reg_save_frame_size = 32 /* float */ + 30 /* integer excluding x3, x4 */ +}; + +// Save off registers which might be killed by calls into the runtime. +// Tries to smart of about FPU registers. In particular we separate +// saving and describing the FPU registers for deoptimization since we +// have to save the FPU registers twice if we describe them. The +// deopt blob is the only thing which needs to describe FPU registers. +// In all other cases it should be sufficient to simply save their +// current value. + +static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs]; +static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs]; + +static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { + int frame_size_in_bytes = reg_save_frame_size * BytesPerWord; + sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); + int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); + OopMap* oop_map = new OopMap(frame_size_in_slots, 0); + assert_cond(oop_map != NULL); + + // caller save registers only, see FrameMap::initialize + // in c1_FrameMap_riscv.cpp for detail. + const static Register caller_save_cpu_regs[FrameMap::max_nof_caller_save_cpu_regs] = { + x7, x10, x11, x12, x13, x14, x15, x16, x17, x28, x29, x30, x31 + }; + + for (int i = 0; i < FrameMap::max_nof_caller_save_cpu_regs; i++) { + Register r = caller_save_cpu_regs[i]; + int sp_offset = cpu_reg_save_offsets[r->encoding()]; + oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset), + r->as_VMReg()); + } + + // fpu_regs + if (save_fpu_registers) { + for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { + FloatRegister r = as_FloatRegister(i); + int sp_offset = fpu_reg_save_offsets[i]; + oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset), + r->as_VMReg()); + } + } + return oop_map; +} + +static OopMap* save_live_registers(StubAssembler* sasm, + bool save_fpu_registers = true) { + __ block_comment("save_live_registers"); + + // if the number of pushed regs is odd, one slot will be reserved for alignment + __ push_reg(RegSet::range(x5, x31), sp); // integer registers except ra(x1) & sp(x2) & gp(x3) & tp(x4) + + if (save_fpu_registers) { + // float registers + __ addi(sp, sp, -(FrameMap::nof_fpu_regs * wordSize)); + for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { + __ fsd(as_FloatRegister(i), Address(sp, i * wordSize)); + } + } else { + // we define reg_save_layout = 62 as the fixed frame size, + // we should also sub 32 * wordSize to sp when save_fpu_registers == false + __ addi(sp, sp, -32 * wordSize); + } + + return generate_oop_map(sasm, save_fpu_registers); +} + +static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { + if (restore_fpu_registers) { + for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { + __ fld(as_FloatRegister(i), Address(sp, i * wordSize)); + } + __ addi(sp, sp, FrameMap::nof_fpu_regs * wordSize); + } else { + // we define reg_save_layout = 64 as the fixed frame size, + // we should also add 32 * wordSize to sp when save_fpu_registers == false + __ addi(sp, sp, 32 * wordSize); + } + + // if the number of popped regs is odd, the reserved slot for alignment will be removed + __ pop_reg(RegSet::range(x5, x31), sp); // integer registers except ra(x1) & sp(x2) & gp(x3) & tp(x4) +} + +static void restore_live_registers_except_r10(StubAssembler* sasm, bool restore_fpu_registers = true) { + if (restore_fpu_registers) { + for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { + __ fld(as_FloatRegister(i), Address(sp, i * wordSize)); + } + __ addi(sp, sp, FrameMap::nof_fpu_regs * wordSize); + } else { + // we define reg_save_layout = 64 as the fixed frame size, + // we should also add 32 * wordSize to sp when save_fpu_registers == false + __ addi(sp, sp, 32 * wordSize); + } + + // pop integer registers except ra(x1) & sp(x2) & gp(x3) & tp(x4) & x10 + // there is one reserved slot for alignment on the stack in save_live_registers(). + __ pop_reg(RegSet::range(x5, x9), sp); // pop x5 ~ x9 with the reserved slot for alignment + __ pop_reg(RegSet::range(x11, x31), sp); // pop x11 ~ x31; x10 will be automatically skipped here +} + +void Runtime1::initialize_pd() { + int i = 0; + int sp_offset = 0; + const int step = 2; // SP offsets are in halfwords + + // all float registers are saved explicitly + for (i = 0; i < FrameMap::nof_fpu_regs; i++) { + fpu_reg_save_offsets[i] = sp_offset; + sp_offset += step; + } + + // a slot reserved for stack 16-byte alignment, see MacroAssembler::push_reg + sp_offset += step; + // we save x5 ~ x31, except x0 ~ x4: loop starts from x5 + for (i = 5; i < FrameMap::nof_cpu_regs; i++) { + cpu_reg_save_offsets[i] = sp_offset; + sp_offset += step; + } +} + +// target: the entry point of the method that creates and posts the exception oop +// has_argument: true if the exception needs arguments (passed in t0 and t1) + +OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { + // make a frame and preserve the caller's caller-save registers + OopMap* oop_map = save_live_registers(sasm); + assert_cond(oop_map != NULL); + int call_offset = 0; + if (!has_argument) { + call_offset = __ call_RT(noreg, noreg, target); + } else { + __ mv(c_rarg1, t0); + __ mv(c_rarg2, t1); + call_offset = __ call_RT(noreg, noreg, target); + } + OopMapSet* oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, oop_map); + + return oop_maps; +} + +OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { + __ block_comment("generate_handle_exception"); + + // incoming parameters + const Register exception_oop = x10; + const Register exception_pc = x13; + + OopMapSet* oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + OopMap* oop_map = NULL; + + switch (id) { + case forward_exception_id: + // We're handling an exception in the context of a compiled frame. + // The registers have been saved in the standard places. Perform + // an exception lookup in the caller and dispatch to the handler + // if found. Otherwise unwind and dispatch to the callers + // exception handler. + oop_map = generate_oop_map(sasm, 1 /* thread */); + + // load and clear pending exception oop into x10 + __ ld(exception_oop, Address(xthread, Thread::pending_exception_offset())); + __ sd(zr, Address(xthread, Thread::pending_exception_offset())); + + // load issuing PC (the return address for this stub) into x13 + __ ld(exception_pc, Address(fp, frame::return_addr_offset * BytesPerWord)); + + // make sure that the vm_results are cleared (may be unnecessary) + __ sd(zr, Address(xthread, JavaThread::vm_result_offset())); + __ sd(zr, Address(xthread, JavaThread::vm_result_2_offset())); + break; + case handle_exception_nofpu_id: + case handle_exception_id: + // At this point all registers MAY be live. + oop_map = save_live_registers(sasm, id != handle_exception_nofpu_id); + break; + case handle_exception_from_callee_id: { + // At this point all registers except exception oop (x10) and + // exception pc (ra) are dead. + const int frame_size = 2 /* fp, return address */; + oop_map = new OopMap(frame_size * VMRegImpl::slots_per_word, 0); + sasm->set_frame_size(frame_size); + break; + } + default: ShouldNotReachHere(); + } + + // verify that only x10 and x13 are valid at this time + __ invalidate_registers(false, true, true, false, true, true); + // verify that x10 contains a valid exception + __ verify_not_null_oop(exception_oop); + +#ifdef ASSERT + // check that fields in JavaThread for exception oop and issuing pc are + // empty before writing to them + Label oop_empty; + __ ld(t0, Address(xthread, JavaThread::exception_oop_offset())); + __ beqz(t0, oop_empty); + __ stop("exception oop already set"); + __ bind(oop_empty); + + Label pc_empty; + __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); + __ beqz(t0, pc_empty); + __ stop("exception pc already set"); + __ bind(pc_empty); +#endif + + // save exception oop and issuing pc into JavaThread + // (exception handler will load it from here) + __ sd(exception_oop, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(exception_pc, Address(xthread, JavaThread::exception_pc_offset())); + + // patch throwing pc into return address (has bci & oop map) + __ sd(exception_pc, Address(fp, frame::return_addr_offset * BytesPerWord)); + + // compute the exception handler. + // the exception oop and the throwing pc are read from the fields in JavaThread + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); + guarantee(oop_map != NULL, "NULL oop_map!"); + oop_maps->add_gc_map(call_offset, oop_map); + + // x10: handler address + // will be the deopt blob if nmethod was deoptimized while we looked up + // handler regardless of whether handler existed in the nmethod. + + // only x10 is valid at this time, all other registers have been destroyed by the runtime call + __ invalidate_registers(false, true, true, true, true, true); + + // patch the return address, this stub will directly return to the exception handler + __ sd(x10, Address(fp, frame::return_addr_offset * BytesPerWord)); + + switch (id) { + case forward_exception_id: + case handle_exception_nofpu_id: + case handle_exception_id: + // Restore the registers that were saved at the beginning. + restore_live_registers(sasm, id != handle_exception_nofpu_id); + break; + case handle_exception_from_callee_id: + break; + default: ShouldNotReachHere(); + } + + return oop_maps; +} + + +void Runtime1::generate_unwind_exception(StubAssembler *sasm) { + // incoming parameters + const Register exception_oop = x10; + // other registers used in this stub + const Register handler_addr = x11; + + // verify that only x10, is valid at this time + __ invalidate_registers(false, true, true, true, true, true); + +#ifdef ASSERT + // check that fields in JavaThread for exception oop and issuing pc are empty + Label oop_empty; + __ ld(t0, Address(xthread, JavaThread::exception_oop_offset())); + __ beqz(t0, oop_empty); + __ stop("exception oop must be empty"); + __ bind(oop_empty); + + Label pc_empty; + __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); + __ beqz(t0, pc_empty); + __ stop("exception pc must be empty"); + __ bind(pc_empty); +#endif + + // Save our return address because + // exception_handler_for_return_address will destroy it. We also + // save exception_oop + __ addi(sp, sp, -2 * wordSize); + __ sd(exception_oop, Address(sp, wordSize)); + __ sd(ra, Address(sp)); + + // 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), xthread, ra); + // x10: exception handler address of the caller + + // Only x10 is valid at this time; all other registers have been + // destroyed by the call. + __ invalidate_registers(false, true, true, true, false, true); + + // move result of call into correct register + __ mv(handler_addr, x10); + + // get throwing pc (= return address). + // ra has been destroyed by the call + __ ld(ra, Address(sp)); + __ ld(exception_oop, Address(sp, wordSize)); + __ addi(sp, sp, 2 * wordSize); + __ mv(x13, ra); + + __ verify_not_null_oop(exception_oop); + + // continue at exception handler (return address removed) + // note: do *not* remove arguments when unwinding the + // activation since the caller assumes having + // all arguments on the stack when entering the + // runtime to determine the exception handler + // (GC happens at call site with arguments!) + // x10: exception oop + // x13: throwing pc + // x11: exception handler + __ jr(handler_addr); +} + +OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { + // use the maximum number of runtime-arguments here because it is difficult to + // distinguish each RT-Call. + // Note: This number affects also the RT-Call in generate_handle_exception because + // the oop-map is shared for all calls. + DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); + assert(deopt_blob != NULL, "deoptimization blob must have been created"); + + OopMap* oop_map = save_live_registers(sasm); + assert_cond(oop_map != NULL); + + __ mv(c_rarg0, xthread); + Label retaddr; + __ set_last_Java_frame(sp, fp, retaddr, t0); + // do the call + int32_t off = 0; + __ la_patchable(t0, RuntimeAddress(target), off); + __ jalr(x1, t0, off); + __ bind(retaddr); + OopMapSet* oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(__ offset(), oop_map); + // verify callee-saved register +#ifdef ASSERT + { Label L; + __ get_thread(t0); + __ beq(xthread, t0, L); + __ stop("StubAssembler::call_RT: xthread not callee saved?"); + __ bind(L); + } +#endif + __ reset_last_Java_frame(true); + +#ifdef ASSERT + // Check that fields in JavaThread for exception oop and issuing pc are empty + Label oop_empty; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ beqz(t0, oop_empty); + __ stop("exception oop must be empty"); + __ bind(oop_empty); + + Label pc_empty; + __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); + __ beqz(t0, pc_empty); + __ stop("exception pc must be empty"); + __ bind(pc_empty); +#endif + + // Runtime will return true if the nmethod has been deoptimized, this is the + // expected scenario and anything else is an error. Note that we maintain a + // check on the result purely as a defensive measure. + Label no_deopt; + __ beqz(x10, no_deopt); // Have we deoptimized? + + // Perform a re-execute. The proper return address is already on the stack, + // we just need to restore registers, pop all of our frames but the return + // address and jump to the deopt blob. + + restore_live_registers(sasm); + __ leave(); + __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); + + __ bind(no_deopt); + __ stop("deopt not performed"); + + return oop_maps; +} + +OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { + // for better readability + const bool dont_gc_arguments = false; + + // default value; overwritten for some optimized stubs that are called from methods that do not use the fpu + bool save_fpu_registers = true; + + // stub code & info for the different stubs + OopMapSet* oop_maps = NULL; + switch (id) { + { + case forward_exception_id: + { + oop_maps = generate_handle_exception(id, sasm); + __ leave(); + __ ret(); + } + break; + + case throw_div0_exception_id: + { + StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); + } + break; + + case throw_null_pointer_exception_id: + { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); + } + break; + + case new_instance_id: + case fast_new_instance_id: + case fast_new_instance_init_check_id: + { + Register klass = x13; // Incoming + Register obj = x10; // Result + + if (id == new_instance_id) { + __ set_info("new_instance", dont_gc_arguments); + } else if (id == fast_new_instance_id) { + __ set_info("fast new_instance", dont_gc_arguments); + } else { + assert(id == fast_new_instance_init_check_id, "bad StubID"); + __ set_info("fast new_instance init check", dont_gc_arguments); + } + + // If TLAB is disabled, see if there is support for inlining contiguous + // allocations. + // Otherwise, just go to the slow path. + if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && + !UseTLAB && Universe::heap()->supports_inline_contig_alloc()) { + Label slow_path; + Register obj_size = x12; + Register tmp1 = x9; + Register tmp2 = x14; + assert_different_registers(klass, obj, obj_size, tmp1, tmp2); + + const int sp_offset = 2; + const int x9_offset = 1; + const int zr_offset = 0; + __ addi(sp, sp, -(sp_offset * wordSize)); + __ sd(x9, Address(sp, x9_offset * wordSize)); + __ sd(zr, Address(sp, zr_offset * wordSize)); + + if (id == fast_new_instance_init_check_id) { + // make sure the klass is initialized + __ lbu(t0, Address(klass, InstanceKlass::init_state_offset())); + __ mv(t1, InstanceKlass::fully_initialized); + __ bne(t0, t1, slow_path); + } + +#ifdef ASSERT + // assert object can be fast path allocated + { + Label ok, not_ok; + __ lw(obj_size, Address(klass, Klass::layout_helper_offset())); + // make sure it's an instance. For instances, layout helper is a positive number. + // For arrays, layout helper is a negative number + __ blez(obj_size, not_ok); + __ andi(t0, obj_size, Klass::_lh_instance_slow_path_bit); + __ beqz(t0, ok); + __ bind(not_ok); + __ stop("assert(can be fast path allocated)"); + __ should_not_reach_here(); + __ bind(ok); + } +#endif // ASSERT + + // get the instance size + __ lwu(obj_size, Address(klass, Klass::layout_helper_offset())); + + __ eden_allocate(obj, obj_size, 0, tmp1, slow_path); + + __ initialize_object(obj, klass, obj_size, 0, tmp1, tmp2, /* is_tlab_allocated */ false); + __ verify_oop(obj); + __ ld(x9, Address(sp, x9_offset * wordSize)); + __ ld(zr, Address(sp, zr_offset * wordSize)); + __ addi(sp, sp, sp_offset * wordSize); + __ ret(); + + __ bind(slow_path); + __ ld(x9, Address(sp, x9_offset * wordSize)); + __ ld(zr, Address(sp, zr_offset * wordSize)); + __ addi(sp, sp, sp_offset * wordSize); + } + + __ enter(); + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); + int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass); + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers_except_r10(sasm); + __ verify_oop(obj); + __ leave(); + __ ret(); + + // x10: new instance + } + + break; + + case counter_overflow_id: + { + Register bci = x10; + Register method = x11; + __ enter(); + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); + + const int bci_off = 0; + const int method_off = 1; + // Retrieve bci + __ lw(bci, Address(fp, bci_off * BytesPerWord)); + // And a pointer to the Method* + __ ld(method, Address(fp, method_off * BytesPerWord)); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method); + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers(sasm); + __ leave(); + __ ret(); + } + break; + + case new_type_array_id: + case new_object_array_id: + { + Register length = x9; // Incoming + Register klass = x13; // Incoming + Register obj = x10; // Result + + if (id == new_type_array_id) { + __ set_info("new_type_array", dont_gc_arguments); + } else { + __ set_info("new_object_array", dont_gc_arguments); + } + +#ifdef ASSERT + // assert object type is really an array of the proper kind + { + Label ok; + Register tmp = obj; + __ lwu(tmp, Address(klass, Klass::layout_helper_offset())); + __ sraiw(tmp, tmp, Klass::_lh_array_tag_shift); + int tag = ((id == new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value); + __ mv(t0, tag); + __ beq(t0, tmp, ok); + __ stop("assert(is an array klass)"); + __ should_not_reach_here(); + __ bind(ok); + } +#endif // ASSERT + + // If TLAB is disabled, see if there is support for inlining contiguous + // allocations. + // Otherwise, just go to the slow path. + if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) { + Register arr_size = x14; + Register tmp1 = x12; + Register tmp2 = x15; + Label slow_path; + assert_different_registers(length, klass, obj, arr_size, tmp1, tmp2); + + // check that array length is small enough for fast path. + __ mv(t0, C1_MacroAssembler::max_array_allocation_length); + __ bgtu(length, t0, slow_path); + + // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) + __ lwu(tmp1, Address(klass, Klass::layout_helper_offset())); + __ andi(t0, tmp1, 0x1f); + __ sll(arr_size, length, t0); + int lh_header_size_width = exact_log2(Klass::_lh_header_size_mask + 1); + int lh_header_size_msb = Klass::_lh_header_size_shift + lh_header_size_width; + __ slli(tmp1, tmp1, XLEN - lh_header_size_msb); + __ srli(tmp1, tmp1, XLEN - lh_header_size_width); + __ add(arr_size, arr_size, tmp1); + __ addi(arr_size, arr_size, MinObjAlignmentInBytesMask); // align up + __ andi(arr_size, arr_size, ~(uint)MinObjAlignmentInBytesMask); + + __ eden_allocate(obj, arr_size, 0, tmp1, slow_path); // preserves arr_size + + __ initialize_header(obj, klass, length, tmp1, tmp2); + __ lbu(tmp1, Address(klass, + in_bytes(Klass::layout_helper_offset()) + + (Klass::_lh_header_size_shift / BitsPerByte))); + assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); + assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise"); + __ andi(tmp1, tmp1, Klass::_lh_header_size_mask); + __ sub(arr_size, arr_size, tmp1); // body length + __ add(tmp1, tmp1, obj); // body start + __ initialize_body(tmp1, arr_size, 0, tmp2); + __ membar(MacroAssembler::StoreStore); + __ verify_oop(obj); + + __ ret(); + + __ bind(slow_path); + } + + __ enter(); + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); + int call_offset = 0; + if (id == new_type_array_id) { + call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); + } else { + call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); + } + + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers_except_r10(sasm); + + __ verify_oop(obj); + __ leave(); + __ ret(); + + // x10: new array + } + break; + + case new_multi_array_id: + { + StubFrame f(sasm, "new_multi_array", dont_gc_arguments); + // x10: klass + // x9: rank + // x12: address of 1st dimension + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); + __ mv(c_rarg1, x10); + __ mv(c_rarg3, x12); + __ mv(c_rarg2, x9); + int call_offset = __ call_RT(x10, noreg, CAST_FROM_FN_PTR(address, new_multi_array), x11, x12, x13); + + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers_except_r10(sasm); + + // x10: new multi array + __ verify_oop(x10); + } + break; + + case register_finalizer_id: + { + __ set_info("register_finalizer", dont_gc_arguments); + + // This is called via call_runtime so the arguments + // will be place in C abi locations + __ verify_oop(c_rarg0); + + // load the klass and check the has finalizer flag + Label register_finalizer; + Register t = x15; + __ load_klass(t, x10); + __ lwu(t, Address(t, Klass::access_flags_offset())); + __ andi(t0, t, JVM_ACC_HAS_FINALIZER); + __ bnez(t0, register_finalizer); + __ ret(); + + __ bind(register_finalizer); + __ enter(); + OopMap* oop_map = save_live_registers(sasm); + assert_cond(oop_map != NULL); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), x10); + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, oop_map); + + // Now restore all the live registers + restore_live_registers(sasm); + + __ leave(); + __ ret(); + } + break; + + case throw_class_cast_exception_id: + { + StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); + } + break; + + case throw_incompatible_class_change_error_id: + { + StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, + CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); + } + break; + + case slow_subtype_check_id: + { + // Typical calling sequence: + // push klass_RInfo (object klass or other subclass) + // push sup_k_RInfo (array element klass or other superclass) + // jump to slow_subtype_check + // Note that the subclass is pushed first, and is therefore deepest. + enum layout { + x10_off, x10_off_hi, + x12_off, x12_off_hi, + x14_off, x14_off_hi, + x15_off, x15_off_hi, + sup_k_off, sup_k_off_hi, + klass_off, klass_off_hi, + framesize, + result_off = sup_k_off + }; + + __ set_info("slow_subtype_check", dont_gc_arguments); + __ push_reg(RegSet::of(x10, x12, x14, x15), sp); + + __ ld(x14, Address(sp, (klass_off) * VMRegImpl::stack_slot_size)); // sub klass + __ ld(x10, Address(sp, (sup_k_off) * VMRegImpl::stack_slot_size)); // super klass + + Label miss; + __ check_klass_subtype_slow_path(x14, x10, x12, x15, NULL, &miss); + + // fallthrough on success: + __ li(t0, 1); + __ sd(t0, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result + __ pop_reg(RegSet::of(x10, x12, x14, x15), sp); + __ ret(); + + __ bind(miss); + __ sd(zr, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result + __ pop_reg(RegSet::of(x10, x12, x14, x15), sp); + __ ret(); + } + break; + + case monitorenter_nofpu_id: + save_fpu_registers = false; + // fall through + case monitorenter_id: + { + StubFrame f(sasm, "monitorenter", dont_gc_arguments); + OopMap* map = save_live_registers(sasm, save_fpu_registers); + assert_cond(map != NULL); + + // Called with store_parameter and not C abi + f.load_argument(1, x10); // x10: object + f.load_argument(0, x11); // x11: lock address + + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), x10, x11); + + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers(sasm, save_fpu_registers); + } + break; + + case monitorexit_nofpu_id: + save_fpu_registers = false; + // fall through + case monitorexit_id: + { + StubFrame f(sasm, "monitorexit", dont_gc_arguments); + OopMap* map = save_live_registers(sasm, save_fpu_registers); + assert_cond(map != NULL); + + // Called with store_parameter and not C abi + f.load_argument(0, x10); // x10: lock address + + // note: really a leaf routine but must setup last java sp + // => use call_RT for now (speed can be improved by + // doing last java sp setup manually) + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), x10); + + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers(sasm, save_fpu_registers); + } + break; + + case deoptimize_id: + { + StubFrame f(sasm, "deoptimize", dont_gc_arguments, does_not_return); + OopMap* oop_map = save_live_registers(sasm); + assert_cond(oop_map != NULL); + f.load_argument(0, c_rarg1); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, deoptimize), c_rarg1); + + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, oop_map); + restore_live_registers(sasm); + DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); + assert(deopt_blob != NULL, "deoptimization blob must have been created"); + __ leave(); + __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); + } + break; + + case throw_range_check_failed_id: + { + StubFrame f(sasm, "range_check_failed", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); + } + break; + + case unwind_exception_id: + { + __ set_info("unwind_exception", dont_gc_arguments); + // note: no stubframe since we are about to leave the current + // activation and we are calling a leaf VM function only. + generate_unwind_exception(sasm); + } + break; + + case access_field_patching_id: + { + StubFrame f(sasm, "access_field_patching", dont_gc_arguments, does_not_return); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); + } + break; + + case load_klass_patching_id: + { + StubFrame f(sasm, "load_klass_patching", dont_gc_arguments, does_not_return); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); + } + break; + + case load_mirror_patching_id: + { + StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments, does_not_return); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); + } + break; + + case load_appendix_patching_id: + { + StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments, does_not_return); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); + } + break; + + case handle_exception_nofpu_id: + case handle_exception_id: + { + StubFrame f(sasm, "handle_exception", dont_gc_arguments); + oop_maps = generate_handle_exception(id, sasm); + } + break; + + case handle_exception_from_callee_id: + { + StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); + oop_maps = generate_handle_exception(id, sasm); + } + break; + + case throw_index_exception_id: + { + StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments, does_not_return); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); + } + break; + + case throw_array_store_exception_id: + { + StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments, does_not_return); + // tos + 0: link + // + 1: return address + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); + } + break; + + case predicate_failed_trap_id: + { + StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments, does_not_return); + + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); + + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap)); + oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers(sasm); + __ leave(); + DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); + assert(deopt_blob != NULL, "deoptimization blob must have been created"); + + __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); + } + break; + + case dtrace_object_alloc_id: + { // c_rarg0: object + StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); + save_live_registers(sasm); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), c_rarg0); + + restore_live_registers(sasm); + } + break; + + default: + { + StubFrame f(sasm, "unimplemented entry", dont_gc_arguments, does_not_return); + __ li(x10, (int) id); + __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), x10); + __ should_not_reach_here(); + } + break; + } + } + return oop_maps; +} + +#undef __ + +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fe46f7b21c86553f004feff6e195b4f446e6a0c4 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C1_GLOBALS_RISCV_HPP +#define CPU_RISCV_C1_GLOBALS_RISCV_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the client compiler. +// (see c1_globals.hpp) + +#ifndef COMPILER2 +define_pd_global(bool, BackgroundCompilation, true ); +define_pd_global(bool, InlineIntrinsics, true ); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, false); +define_pd_global(bool, UseOnStackReplacement, true ); +define_pd_global(bool, TieredCompilation, false); +define_pd_global(intx, CompileThreshold, 1500 ); + +define_pd_global(intx, OnStackReplacePercentage, 933 ); +define_pd_global(intx, NewSizeThreadIncrease, 4*K ); +define_pd_global(intx, InitialCodeCacheSize, 160*K); +define_pd_global(intx, ReservedCodeCacheSize, 32*M ); +define_pd_global(intx, NonProfiledCodeHeapSize, 13*M ); +define_pd_global(intx, ProfiledCodeHeapSize, 14*M ); +define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(bool, ProfileInterpreter, false); +define_pd_global(intx, CodeCacheExpansionSize, 32*K ); +define_pd_global(uintx, CodeCacheMinBlockLength, 1); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(bool, NeverActAsServerClassMachine, true ); +define_pd_global(uint64_t, MaxRAM, 1ULL*G); +define_pd_global(bool, CICompileOSR, true ); +#endif // !COMPILER2 +define_pd_global(bool, UseTypeProfile, false); + +define_pd_global(bool, OptimizeSinglePrecision, true ); +define_pd_global(bool, CSEArrayLength, false); +define_pd_global(bool, TwoOperandLIRForm, false); + +#endif // CPU_RISCV_C1_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27770dc17aac0f063e56bd7b61d7179a3de9a664 --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -0,0 +1,1646 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/assembler.inline.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/intrinsicnode.hpp" +#include "opto/subnode.hpp" +#include "runtime/stubRoutines.hpp" + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#define STOP(error) stop(error) +#else +#define BLOCK_COMMENT(str) block_comment(str) +#define STOP(error) block_comment(error); stop(error) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +// short string +// StringUTF16.indexOfChar +// StringLatin1.indexOfChar +void C2_MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, + Register ch, Register result, + bool isL) +{ + Register ch1 = t0; + Register index = t1; + + BLOCK_COMMENT("string_indexof_char_short {"); + + Label LOOP, LOOP1, LOOP4, LOOP8; + Label MATCH, MATCH1, MATCH2, MATCH3, + MATCH4, MATCH5, MATCH6, MATCH7, NOMATCH; + + mv(result, -1); + mv(index, zr); + + bind(LOOP); + addi(t0, index, 8); + ble(t0, cnt1, LOOP8); + addi(t0, index, 4); + ble(t0, cnt1, LOOP4); + j(LOOP1); + + bind(LOOP8); + isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); + beq(ch, ch1, MATCH); + isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); + beq(ch, ch1, MATCH1); + isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); + beq(ch, ch1, MATCH2); + isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); + beq(ch, ch1, MATCH3); + isL ? lbu(ch1, Address(str1, 4)) : lhu(ch1, Address(str1, 8)); + beq(ch, ch1, MATCH4); + isL ? lbu(ch1, Address(str1, 5)) : lhu(ch1, Address(str1, 10)); + beq(ch, ch1, MATCH5); + isL ? lbu(ch1, Address(str1, 6)) : lhu(ch1, Address(str1, 12)); + beq(ch, ch1, MATCH6); + isL ? lbu(ch1, Address(str1, 7)) : lhu(ch1, Address(str1, 14)); + beq(ch, ch1, MATCH7); + addi(index, index, 8); + addi(str1, str1, isL ? 8 : 16); + blt(index, cnt1, LOOP); + j(NOMATCH); + + bind(LOOP4); + isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); + beq(ch, ch1, MATCH); + isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); + beq(ch, ch1, MATCH1); + isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); + beq(ch, ch1, MATCH2); + isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); + beq(ch, ch1, MATCH3); + addi(index, index, 4); + addi(str1, str1, isL ? 4 : 8); + bge(index, cnt1, NOMATCH); + + bind(LOOP1); + isL ? lbu(ch1, Address(str1)) : lhu(ch1, Address(str1)); + beq(ch, ch1, MATCH); + addi(index, index, 1); + addi(str1, str1, isL ? 1 : 2); + blt(index, cnt1, LOOP1); + j(NOMATCH); + + bind(MATCH1); + addi(index, index, 1); + j(MATCH); + + bind(MATCH2); + addi(index, index, 2); + j(MATCH); + + bind(MATCH3); + addi(index, index, 3); + j(MATCH); + + bind(MATCH4); + addi(index, index, 4); + j(MATCH); + + bind(MATCH5); + addi(index, index, 5); + j(MATCH); + + bind(MATCH6); + addi(index, index, 6); + j(MATCH); + + bind(MATCH7); + addi(index, index, 7); + + bind(MATCH); + mv(result, index); + bind(NOMATCH); + BLOCK_COMMENT("} string_indexof_char_short"); +} + +// StringUTF16.indexOfChar +// StringLatin1.indexOfChar +void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, + Register ch, Register result, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + bool isL) +{ + Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; + Register ch1 = t0; + Register orig_cnt = t1; + Register mask1 = tmp3; + Register mask2 = tmp2; + Register match_mask = tmp1; + Register trailing_char = tmp4; + Register unaligned_elems = tmp4; + + BLOCK_COMMENT("string_indexof_char {"); + beqz(cnt1, NOMATCH); + + addi(t0, cnt1, isL ? -32 : -16); + bgtz(t0, DO_LONG); + string_indexof_char_short(str1, cnt1, ch, result, isL); + j(DONE); + + bind(DO_LONG); + mv(orig_cnt, cnt1); + if (AvoidUnalignedAccesses) { + Label ALIGNED; + andi(unaligned_elems, str1, 0x7); + beqz(unaligned_elems, ALIGNED); + sub(unaligned_elems, unaligned_elems, 8); + neg(unaligned_elems, unaligned_elems); + if (!isL) { + srli(unaligned_elems, unaligned_elems, 1); + } + // do unaligned part per element + string_indexof_char_short(str1, unaligned_elems, ch, result, isL); + bgez(result, DONE); + mv(orig_cnt, cnt1); + sub(cnt1, cnt1, unaligned_elems); + bind(ALIGNED); + } + + // duplicate ch + if (isL) { + slli(ch1, ch, 8); + orr(ch, ch1, ch); + } + slli(ch1, ch, 16); + orr(ch, ch1, ch); + slli(ch1, ch, 32); + orr(ch, ch1, ch); + + if (!isL) { + slli(cnt1, cnt1, 1); + } + + uint64_t mask0101 = UCONST64(0x0101010101010101); + uint64_t mask0001 = UCONST64(0x0001000100010001); + mv(mask1, isL ? mask0101 : mask0001); + uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); + uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); + mv(mask2, isL ? mask7f7f : mask7fff); + + bind(CH1_LOOP); + ld(ch1, Address(str1)); + addi(str1, str1, 8); + addi(cnt1, cnt1, -8); + compute_match_mask(ch1, ch, match_mask, mask1, mask2); + bnez(match_mask, HIT); + bgtz(cnt1, CH1_LOOP); + j(NOMATCH); + + bind(HIT); + ctzc_bit(trailing_char, match_mask, isL, ch1, result); + srli(trailing_char, trailing_char, 3); + addi(cnt1, cnt1, 8); + ble(cnt1, trailing_char, NOMATCH); + // match case + if (!isL) { + srli(cnt1, cnt1, 1); + srli(trailing_char, trailing_char, 1); + } + + sub(result, orig_cnt, cnt1); + add(result, result, trailing_char); + j(DONE); + + bind(NOMATCH); + mv(result, -1); + + bind(DONE); + BLOCK_COMMENT("} string_indexof_char"); +} + +typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); + +// Search for needle in haystack and return index or -1 +// x10: result +// x11: haystack +// x12: haystack_len +// x13: needle +// x14: needle_len +void C2_MacroAssembler::string_indexof(Register haystack, Register needle, + Register haystack_len, Register needle_len, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + Register tmp5, Register tmp6, + Register result, int ae) +{ + assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); + + Label LINEARSEARCH, LINEARSTUB, DONE, NOMATCH; + + Register ch1 = t0; + Register ch2 = t1; + Register nlen_tmp = tmp1; // needle len tmp + Register hlen_tmp = tmp2; // haystack len tmp + Register result_tmp = tmp4; + + bool isLL = ae == StrIntrinsicNode::LL; + + bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; + bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; + int needle_chr_shift = needle_isL ? 0 : 1; + int haystack_chr_shift = haystack_isL ? 0 : 1; + int needle_chr_size = needle_isL ? 1 : 2; + int haystack_chr_size = haystack_isL ? 1 : 2; + load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : + (load_chr_insn)&MacroAssembler::lhu; + load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : + (load_chr_insn)&MacroAssembler::lhu; + + BLOCK_COMMENT("string_indexof {"); + + // Note, inline_string_indexOf() generates checks: + // if (pattern.count > src.count) return -1; + // if (pattern.count == 0) return 0; + + // We have two strings, a source string in haystack, haystack_len and a pattern string + // in needle, needle_len. Find the first occurence of pattern in source or return -1. + + // For larger pattern and source we use a simplified Boyer Moore algorithm. + // With a small pattern and source we use linear scan. + + // needle_len >=8 && needle_len < 256 && needle_len < haystack_len/4, use bmh algorithm. + sub(result_tmp, haystack_len, needle_len); + // needle_len < 8, use linear scan + sub(t0, needle_len, 8); + bltz(t0, LINEARSEARCH); + // needle_len >= 256, use linear scan + sub(t0, needle_len, 256); + bgez(t0, LINEARSTUB); + // needle_len >= haystack_len/4, use linear scan + srli(t0, haystack_len, 2); + bge(needle_len, t0, LINEARSTUB); + + // Boyer-Moore-Horspool introduction: + // The Boyer Moore alogorithm is based on the description here:- + // + // http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm + // + // This describes and algorithm with 2 shift rules. The 'Bad Character' rule + // and the 'Good Suffix' rule. + // + // These rules are essentially heuristics for how far we can shift the + // pattern along the search string. + // + // The implementation here uses the 'Bad Character' rule only because of the + // complexity of initialisation for the 'Good Suffix' rule. + // + // This is also known as the Boyer-Moore-Horspool algorithm: + // + // http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm + // + // #define ASIZE 256 + // + // int bm(unsigned char *pattern, int m, unsigned char *src, int n) { + // int i, j; + // unsigned c; + // unsigned char bc[ASIZE]; + // + // /* Preprocessing */ + // for (i = 0; i < ASIZE; ++i) + // bc[i] = m; + // for (i = 0; i < m - 1; ) { + // c = pattern[i]; + // ++i; + // // c < 256 for Latin1 string, so, no need for branch + // #ifdef PATTERN_STRING_IS_LATIN1 + // bc[c] = m - i; + // #else + // if (c < ASIZE) bc[c] = m - i; + // #endif + // } + // + // /* Searching */ + // j = 0; + // while (j <= n - m) { + // c = src[i+j]; + // if (pattern[m-1] == c) + // int k; + // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); + // if (k < 0) return j; + // // c < 256 for Latin1 string, so, no need for branch + // #ifdef SOURCE_STRING_IS_LATIN1_AND_PATTERN_STRING_IS_LATIN1 + // // LL case: (c< 256) always true. Remove branch + // j += bc[pattern[j+m-1]]; + // #endif + // #ifdef SOURCE_STRING_IS_UTF_AND_PATTERN_STRING_IS_UTF + // // UU case: need if (c if not. + // if (c < ASIZE) + // j += bc[pattern[j+m-1]]; + // else + // j += m + // #endif + // } + // return -1; + // } + + // temp register:t0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, result + Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH, + BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP; + + Register haystack_end = haystack_len; + Register skipch = tmp2; + + // pattern length is >=8, so, we can read at least 1 register for cases when + // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for + // UL case. We'll re-read last character in inner pre-loop code to have + // single outer pre-loop load + const int firstStep = isLL ? 7 : 3; + + const int ASIZE = 256; + const int STORE_BYTES = 8; // 8 bytes stored per instruction(sd) + + sub(sp, sp, ASIZE); + + // init BC offset table with default value: needle_len + slli(t0, needle_len, 8); + orr(t0, t0, needle_len); // [63...16][needle_len][needle_len] + slli(tmp1, t0, 16); + orr(t0, tmp1, t0); // [63...32][needle_len][needle_len][needle_len][needle_len] + slli(tmp1, t0, 32); + orr(tmp5, tmp1, t0); // tmp5: 8 elements [needle_len] + + mv(ch1, sp); // ch1 is t0 + mv(tmp6, ASIZE / STORE_BYTES); // loop iterations + + bind(BM_INIT_LOOP); + // for (i = 0; i < ASIZE; ++i) + // bc[i] = m; + for (int i = 0; i < 4; i++) { + sd(tmp5, Address(ch1, i * wordSize)); + } + add(ch1, ch1, 32); + sub(tmp6, tmp6, 4); + bgtz(tmp6, BM_INIT_LOOP); + + sub(nlen_tmp, needle_len, 1); // m - 1, index of the last element in pattern + Register orig_haystack = tmp5; + mv(orig_haystack, haystack); + // result_tmp = tmp4 + shadd(haystack_end, result_tmp, haystack, haystack_end, haystack_chr_shift); + sub(ch2, needle_len, 1); // bc offset init value, ch2 is t1 + mv(tmp3, needle); + + // for (i = 0; i < m - 1; ) { + // c = pattern[i]; + // ++i; + // // c < 256 for Latin1 string, so, no need for branch + // #ifdef PATTERN_STRING_IS_LATIN1 + // bc[c] = m - i; + // #else + // if (c < ASIZE) bc[c] = m - i; + // #endif + // } + bind(BCLOOP); + (this->*needle_load_1chr)(ch1, Address(tmp3), noreg); + add(tmp3, tmp3, needle_chr_size); + if (!needle_isL) { + // ae == StrIntrinsicNode::UU + mv(tmp6, ASIZE); + bgeu(ch1, tmp6, BCSKIP); + } + add(tmp4, sp, ch1); + sb(ch2, Address(tmp4)); // store skip offset to BC offset table + + bind(BCSKIP); + sub(ch2, ch2, 1); // for next pattern element, skip distance -1 + bgtz(ch2, BCLOOP); + + // tmp6: pattern end, address after needle + shadd(tmp6, needle_len, needle, tmp6, needle_chr_shift); + if (needle_isL == haystack_isL) { + // load last 8 bytes (8LL/4UU symbols) + ld(tmp6, Address(tmp6, -wordSize)); + } else { + // UL: from UTF-16(source) search Latin1(pattern) + lwu(tmp6, Address(tmp6, -wordSize / 2)); // load last 4 bytes(4 symbols) + // convert Latin1 to UTF. eg: 0x0000abcd -> 0x0a0b0c0d + // We'll have to wait until load completed, but it's still faster than per-character loads+checks + srli(tmp3, tmp6, BitsPerByte * (wordSize / 2 - needle_chr_size)); // pattern[m-1], eg:0x0000000a + slli(ch2, tmp6, XLEN - 24); + srli(ch2, ch2, XLEN - 8); // pattern[m-2], 0x0000000b + slli(ch1, tmp6, XLEN - 16); + srli(ch1, ch1, XLEN - 8); // pattern[m-3], 0x0000000c + andi(tmp6, tmp6, 0xff); // pattern[m-4], 0x0000000d + slli(ch2, ch2, 16); + orr(ch2, ch2, ch1); // 0x00000b0c + slli(result, tmp3, 48); // use result as temp register + orr(tmp6, tmp6, result); // 0x0a00000d + slli(result, ch2, 16); + orr(tmp6, tmp6, result); // UTF-16:0x0a0b0c0d + } + + // i = m - 1; + // skipch = j + i; + // if (skipch == pattern[m - 1] + // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); + // else + // move j with bad char offset table + bind(BMLOOPSTR2); + // compare pattern to source string backward + shadd(result, nlen_tmp, haystack, result, haystack_chr_shift); + (this->*haystack_load_1chr)(skipch, Address(result), noreg); + sub(nlen_tmp, nlen_tmp, firstStep); // nlen_tmp is positive here, because needle_len >= 8 + if (needle_isL == haystack_isL) { + // re-init tmp3. It's for free because it's executed in parallel with + // load above. Alternative is to initialize it before loop, but it'll + // affect performance on in-order systems with 2 or more ld/st pipelines + srli(tmp3, tmp6, BitsPerByte * (wordSize - needle_chr_size)); // UU/LL: pattern[m-1] + } + if (!isLL) { // UU/UL case + slli(ch2, nlen_tmp, 1); // offsets in bytes + } + bne(tmp3, skipch, BMSKIP); // if not equal, skipch is bad char + add(result, haystack, isLL ? nlen_tmp : ch2); + ld(ch2, Address(result)); // load 8 bytes from source string + mv(ch1, tmp6); + if (isLL) { + j(BMLOOPSTR1_AFTER_LOAD); + } else { + sub(nlen_tmp, nlen_tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8 + j(BMLOOPSTR1_CMP); + } + + bind(BMLOOPSTR1); + shadd(ch1, nlen_tmp, needle, ch1, needle_chr_shift); + (this->*needle_load_1chr)(ch1, Address(ch1), noreg); + shadd(ch2, nlen_tmp, haystack, ch2, haystack_chr_shift); + (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); + + bind(BMLOOPSTR1_AFTER_LOAD); + sub(nlen_tmp, nlen_tmp, 1); + bltz(nlen_tmp, BMLOOPSTR1_LASTCMP); + + bind(BMLOOPSTR1_CMP); + beq(ch1, ch2, BMLOOPSTR1); + + bind(BMSKIP); + if (!isLL) { + // if we've met UTF symbol while searching Latin1 pattern, then we can + // skip needle_len symbols + if (needle_isL != haystack_isL) { + mv(result_tmp, needle_len); + } else { + mv(result_tmp, 1); + } + mv(t0, ASIZE); + bgeu(skipch, t0, BMADV); + } + add(result_tmp, sp, skipch); + lbu(result_tmp, Address(result_tmp)); // load skip offset + + bind(BMADV); + sub(nlen_tmp, needle_len, 1); + // move haystack after bad char skip offset + shadd(haystack, result_tmp, haystack, result, haystack_chr_shift); + ble(haystack, haystack_end, BMLOOPSTR2); + add(sp, sp, ASIZE); + j(NOMATCH); + + bind(BMLOOPSTR1_LASTCMP); + bne(ch1, ch2, BMSKIP); + + bind(BMMATCH); + sub(result, haystack, orig_haystack); + if (!haystack_isL) { + srli(result, result, 1); + } + add(sp, sp, ASIZE); + j(DONE); + + bind(LINEARSTUB); + sub(t0, needle_len, 16); // small patterns still should be handled by simple algorithm + bltz(t0, LINEARSEARCH); + mv(result, zr); + RuntimeAddress stub = NULL; + if (isLL) { + stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ll()); + assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated"); + } else if (needle_isL) { + stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ul()); + assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated"); + } else { + stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); + assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); + } + trampoline_call(stub); + j(DONE); + + bind(NOMATCH); + mv(result, -1); + j(DONE); + + bind(LINEARSEARCH); + string_indexof_linearscan(haystack, needle, haystack_len, needle_len, tmp1, tmp2, tmp3, tmp4, -1, result, ae); + + bind(DONE); + BLOCK_COMMENT("} string_indexof"); +} + +// string_indexof +// result: x10 +// src: x11 +// src_count: x12 +// pattern: x13 +// pattern_count: x14 or 1/2/3/4 +void C2_MacroAssembler::string_indexof_linearscan(Register haystack, Register needle, + Register haystack_len, Register needle_len, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + int needle_con_cnt, Register result, int ae) +{ + // Note: + // needle_con_cnt > 0 means needle_len register is invalid, needle length is constant + // for UU/LL: needle_con_cnt[1, 4], UL: needle_con_cnt = 1 + assert(needle_con_cnt <= 4, "Invalid needle constant count"); + assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); + + Register ch1 = t0; + Register ch2 = t1; + Register hlen_neg = haystack_len, nlen_neg = needle_len; + Register nlen_tmp = tmp1, hlen_tmp = tmp2, result_tmp = tmp4; + + bool isLL = ae == StrIntrinsicNode::LL; + + bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; + bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; + int needle_chr_shift = needle_isL ? 0 : 1; + int haystack_chr_shift = haystack_isL ? 0 : 1; + int needle_chr_size = needle_isL ? 1 : 2; + int haystack_chr_size = haystack_isL ? 1 : 2; + + load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : + (load_chr_insn)&MacroAssembler::lhu; + load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : + (load_chr_insn)&MacroAssembler::lhu; + load_chr_insn load_2chr = isLL ? (load_chr_insn)&MacroAssembler::lhu : (load_chr_insn)&MacroAssembler::lwu; + load_chr_insn load_4chr = isLL ? (load_chr_insn)&MacroAssembler::lwu : (load_chr_insn)&MacroAssembler::ld; + + Label DO1, DO2, DO3, MATCH, NOMATCH, DONE; + + Register first = tmp3; + + if (needle_con_cnt == -1) { + Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT; + + sub(t0, needle_len, needle_isL == haystack_isL ? 4 : 2); + bltz(t0, DOSHORT); + + (this->*needle_load_1chr)(first, Address(needle), noreg); + slli(t0, needle_len, needle_chr_shift); + add(needle, needle, t0); + neg(nlen_neg, t0); + slli(t0, result_tmp, haystack_chr_shift); + add(haystack, haystack, t0); + neg(hlen_neg, t0); + + bind(FIRST_LOOP); + add(t0, haystack, hlen_neg); + (this->*haystack_load_1chr)(ch2, Address(t0), noreg); + beq(first, ch2, STR1_LOOP); + + bind(STR2_NEXT); + add(hlen_neg, hlen_neg, haystack_chr_size); + blez(hlen_neg, FIRST_LOOP); + j(NOMATCH); + + bind(STR1_LOOP); + add(nlen_tmp, nlen_neg, needle_chr_size); + add(hlen_tmp, hlen_neg, haystack_chr_size); + bgez(nlen_tmp, MATCH); + + bind(STR1_NEXT); + add(ch1, needle, nlen_tmp); + (this->*needle_load_1chr)(ch1, Address(ch1), noreg); + add(ch2, haystack, hlen_tmp); + (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); + bne(ch1, ch2, STR2_NEXT); + add(nlen_tmp, nlen_tmp, needle_chr_size); + add(hlen_tmp, hlen_tmp, haystack_chr_size); + bltz(nlen_tmp, STR1_NEXT); + j(MATCH); + + bind(DOSHORT); + if (needle_isL == haystack_isL) { + sub(t0, needle_len, 2); + bltz(t0, DO1); + bgtz(t0, DO3); + } + } + + if (needle_con_cnt == 4) { + Label CH1_LOOP; + (this->*load_4chr)(ch1, Address(needle), noreg); + sub(result_tmp, haystack_len, 4); + slli(tmp3, result_tmp, haystack_chr_shift); // result as tmp + add(haystack, haystack, tmp3); + neg(hlen_neg, tmp3); + + bind(CH1_LOOP); + add(ch2, haystack, hlen_neg); + (this->*load_4chr)(ch2, Address(ch2), noreg); + beq(ch1, ch2, MATCH); + add(hlen_neg, hlen_neg, haystack_chr_size); + blez(hlen_neg, CH1_LOOP); + j(NOMATCH); + } + + if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 2) { + Label CH1_LOOP; + BLOCK_COMMENT("string_indexof DO2 {"); + bind(DO2); + (this->*load_2chr)(ch1, Address(needle), noreg); + if (needle_con_cnt == 2) { + sub(result_tmp, haystack_len, 2); + } + slli(tmp3, result_tmp, haystack_chr_shift); + add(haystack, haystack, tmp3); + neg(hlen_neg, tmp3); + + bind(CH1_LOOP); + add(tmp3, haystack, hlen_neg); + (this->*load_2chr)(ch2, Address(tmp3), noreg); + beq(ch1, ch2, MATCH); + add(hlen_neg, hlen_neg, haystack_chr_size); + blez(hlen_neg, CH1_LOOP); + j(NOMATCH); + BLOCK_COMMENT("} string_indexof DO2"); + } + + if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 3) { + Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; + BLOCK_COMMENT("string_indexof DO3 {"); + + bind(DO3); + (this->*load_2chr)(first, Address(needle), noreg); + (this->*needle_load_1chr)(ch1, Address(needle, 2 * needle_chr_size), noreg); + if (needle_con_cnt == 3) { + sub(result_tmp, haystack_len, 3); + } + slli(hlen_tmp, result_tmp, haystack_chr_shift); + add(haystack, haystack, hlen_tmp); + neg(hlen_neg, hlen_tmp); + + bind(FIRST_LOOP); + add(ch2, haystack, hlen_neg); + (this->*load_2chr)(ch2, Address(ch2), noreg); + beq(first, ch2, STR1_LOOP); + + bind(STR2_NEXT); + add(hlen_neg, hlen_neg, haystack_chr_size); + blez(hlen_neg, FIRST_LOOP); + j(NOMATCH); + + bind(STR1_LOOP); + add(hlen_tmp, hlen_neg, 2 * haystack_chr_size); + add(ch2, haystack, hlen_tmp); + (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); + bne(ch1, ch2, STR2_NEXT); + j(MATCH); + BLOCK_COMMENT("} string_indexof DO3"); + } + + if (needle_con_cnt == -1 || needle_con_cnt == 1) { + Label DO1_LOOP; + + BLOCK_COMMENT("string_indexof DO1 {"); + bind(DO1); + (this->*needle_load_1chr)(ch1, Address(needle), noreg); + sub(result_tmp, haystack_len, 1); + mv(tmp3, result_tmp); + if (haystack_chr_shift) { + slli(tmp3, result_tmp, haystack_chr_shift); + } + add(haystack, haystack, tmp3); + neg(hlen_neg, tmp3); + + bind(DO1_LOOP); + add(tmp3, haystack, hlen_neg); + (this->*haystack_load_1chr)(ch2, Address(tmp3), noreg); + beq(ch1, ch2, MATCH); + add(hlen_neg, hlen_neg, haystack_chr_size); + blez(hlen_neg, DO1_LOOP); + BLOCK_COMMENT("} string_indexof DO1"); + } + + bind(NOMATCH); + mv(result, -1); + j(DONE); + + bind(MATCH); + srai(t0, hlen_neg, haystack_chr_shift); + add(result, result_tmp, t0); + + bind(DONE); +} + +// Compare strings. +void C2_MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, + Register tmp3, int ae) +{ + Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, + DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, + SHORT_LOOP_START, TAIL_CHECK, L; + + const int STUB_THRESHOLD = 64 + 8; + bool isLL = ae == StrIntrinsicNode::LL; + bool isLU = ae == StrIntrinsicNode::LU; + bool isUL = ae == StrIntrinsicNode::UL; + + bool str1_isL = isLL || isLU; + bool str2_isL = isLL || isUL; + + // for L strings, 1 byte for 1 character + // for U strings, 2 bytes for 1 character + int str1_chr_size = str1_isL ? 1 : 2; + int str2_chr_size = str2_isL ? 1 : 2; + int minCharsInWord = isLL ? wordSize : wordSize / 2; + + load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; + load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; + + BLOCK_COMMENT("string_compare {"); + + // Bizzarely, the counts are passed in bytes, regardless of whether they + // are L or U strings, however the result is always in characters. + if (!str1_isL) { + sraiw(cnt1, cnt1, 1); + } + if (!str2_isL) { + sraiw(cnt2, cnt2, 1); + } + + // Compute the minimum of the string lengths and save the difference in result. + sub(result, cnt1, cnt2); + bgt(cnt1, cnt2, L); + mv(cnt2, cnt1); + bind(L); + + // A very short string + li(t0, minCharsInWord); + ble(cnt2, t0, SHORT_STRING); + + // Compare longwords + // load first parts of strings and finish initialization while loading + { + if (str1_isL == str2_isL) { // LL or UU + // load 8 bytes once to compare + ld(tmp1, Address(str1)); + beq(str1, str2, DONE); + ld(tmp2, Address(str2)); + li(t0, STUB_THRESHOLD); + bge(cnt2, t0, STUB); + sub(cnt2, cnt2, minCharsInWord); + beqz(cnt2, TAIL_CHECK); + // convert cnt2 from characters to bytes + if (!str1_isL) { + slli(cnt2, cnt2, 1); + } + add(str2, str2, cnt2); + add(str1, str1, cnt2); + sub(cnt2, zr, cnt2); + } else if (isLU) { // LU case + lwu(tmp1, Address(str1)); + ld(tmp2, Address(str2)); + li(t0, STUB_THRESHOLD); + bge(cnt2, t0, STUB); + addi(cnt2, cnt2, -4); + add(str1, str1, cnt2); + sub(cnt1, zr, cnt2); + slli(cnt2, cnt2, 1); + add(str2, str2, cnt2); + inflate_lo32(tmp3, tmp1); + mv(tmp1, tmp3); + sub(cnt2, zr, cnt2); + addi(cnt1, cnt1, 4); + } else { // UL case + ld(tmp1, Address(str1)); + lwu(tmp2, Address(str2)); + li(t0, STUB_THRESHOLD); + bge(cnt2, t0, STUB); + addi(cnt2, cnt2, -4); + slli(t0, cnt2, 1); + sub(cnt1, zr, t0); + add(str1, str1, t0); + add(str2, str2, cnt2); + inflate_lo32(tmp3, tmp2); + mv(tmp2, tmp3); + sub(cnt2, zr, cnt2); + addi(cnt1, cnt1, 8); + } + addi(cnt2, cnt2, isUL ? 4 : 8); + bgez(cnt2, TAIL); + xorr(tmp3, tmp1, tmp2); + bnez(tmp3, DIFFERENCE); + + // main loop + bind(NEXT_WORD); + if (str1_isL == str2_isL) { // LL or UU + add(t0, str1, cnt2); + ld(tmp1, Address(t0)); + add(t0, str2, cnt2); + ld(tmp2, Address(t0)); + addi(cnt2, cnt2, 8); + } else if (isLU) { // LU case + add(t0, str1, cnt1); + lwu(tmp1, Address(t0)); + add(t0, str2, cnt2); + ld(tmp2, Address(t0)); + addi(cnt1, cnt1, 4); + inflate_lo32(tmp3, tmp1); + mv(tmp1, tmp3); + addi(cnt2, cnt2, 8); + } else { // UL case + add(t0, str2, cnt2); + lwu(tmp2, Address(t0)); + add(t0, str1, cnt1); + ld(tmp1, Address(t0)); + inflate_lo32(tmp3, tmp2); + mv(tmp2, tmp3); + addi(cnt1, cnt1, 8); + addi(cnt2, cnt2, 4); + } + bgez(cnt2, TAIL); + + xorr(tmp3, tmp1, tmp2); + beqz(tmp3, NEXT_WORD); + j(DIFFERENCE); + bind(TAIL); + xorr(tmp3, tmp1, tmp2); + bnez(tmp3, DIFFERENCE); + // Last longword. In the case where length == 4 we compare the + // same longword twice, but that's still faster than another + // conditional branch. + if (str1_isL == str2_isL) { // LL or UU + ld(tmp1, Address(str1)); + ld(tmp2, Address(str2)); + } else if (isLU) { // LU case + lwu(tmp1, Address(str1)); + ld(tmp2, Address(str2)); + inflate_lo32(tmp3, tmp1); + mv(tmp1, tmp3); + } else { // UL case + lwu(tmp2, Address(str2)); + ld(tmp1, Address(str1)); + inflate_lo32(tmp3, tmp2); + mv(tmp2, tmp3); + } + bind(TAIL_CHECK); + xorr(tmp3, tmp1, tmp2); + beqz(tmp3, DONE); + + // Find the first different characters in the longwords and + // compute their difference. + bind(DIFFERENCE); + ctzc_bit(result, tmp3, isLL); // count zero from lsb to msb + srl(tmp1, tmp1, result); + srl(tmp2, tmp2, result); + if (isLL) { + andi(tmp1, tmp1, 0xFF); + andi(tmp2, tmp2, 0xFF); + } else { + andi(tmp1, tmp1, 0xFFFF); + andi(tmp2, tmp2, 0xFFFF); + } + sub(result, tmp1, tmp2); + j(DONE); + } + + bind(STUB); + RuntimeAddress stub = NULL; + switch (ae) { + case StrIntrinsicNode::LL: + stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LL()); + break; + case StrIntrinsicNode::UU: + stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UU()); + break; + case StrIntrinsicNode::LU: + stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LU()); + break; + case StrIntrinsicNode::UL: + stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UL()); + break; + default: + ShouldNotReachHere(); + } + assert(stub.target() != NULL, "compare_long_string stub has not been generated"); + trampoline_call(stub); + j(DONE); + + bind(SHORT_STRING); + // Is the minimum length zero? + beqz(cnt2, DONE); + // arrange code to do most branches while loading and loading next characters + // while comparing previous + (this->*str1_load_chr)(tmp1, Address(str1), t0); + addi(str1, str1, str1_chr_size); + addi(cnt2, cnt2, -1); + beqz(cnt2, SHORT_LAST_INIT); + (this->*str2_load_chr)(cnt1, Address(str2), t0); + addi(str2, str2, str2_chr_size); + j(SHORT_LOOP_START); + bind(SHORT_LOOP); + addi(cnt2, cnt2, -1); + beqz(cnt2, SHORT_LAST); + bind(SHORT_LOOP_START); + (this->*str1_load_chr)(tmp2, Address(str1), t0); + addi(str1, str1, str1_chr_size); + (this->*str2_load_chr)(t0, Address(str2), t0); + addi(str2, str2, str2_chr_size); + bne(tmp1, cnt1, SHORT_LOOP_TAIL); + addi(cnt2, cnt2, -1); + beqz(cnt2, SHORT_LAST2); + (this->*str1_load_chr)(tmp1, Address(str1), t0); + addi(str1, str1, str1_chr_size); + (this->*str2_load_chr)(cnt1, Address(str2), t0); + addi(str2, str2, str2_chr_size); + beq(tmp2, t0, SHORT_LOOP); + sub(result, tmp2, t0); + j(DONE); + bind(SHORT_LOOP_TAIL); + sub(result, tmp1, cnt1); + j(DONE); + bind(SHORT_LAST2); + beq(tmp2, t0, DONE); + sub(result, tmp2, t0); + + j(DONE); + bind(SHORT_LAST_INIT); + (this->*str2_load_chr)(cnt1, Address(str2), t0); + addi(str2, str2, str2_chr_size); + bind(SHORT_LAST); + beq(tmp1, cnt1, DONE); + sub(result, tmp1, cnt1); + + bind(DONE); + + BLOCK_COMMENT("} string_compare"); +} + +void C2_MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, + Register tmp4, Register tmp5, Register tmp6, Register result, + Register cnt1, int elem_size) { + Label DONE, SAME, NEXT_DWORD, SHORT, TAIL, TAIL2, IS_TMP5_ZR; + Register tmp1 = t0; + Register tmp2 = t1; + Register cnt2 = tmp2; // cnt2 only used in array length compare + Register elem_per_word = tmp6; + int log_elem_size = exact_log2(elem_size); + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); + + assert(elem_size == 1 || elem_size == 2, "must be char or byte"); + assert_different_registers(a1, a2, result, cnt1, t0, t1, tmp3, tmp4, tmp5, tmp6); + li(elem_per_word, wordSize / elem_size); + + BLOCK_COMMENT("arrays_equals {"); + + // if (a1 == a2), return true + beq(a1, a2, SAME); + + mv(result, false); + beqz(a1, DONE); + beqz(a2, DONE); + lwu(cnt1, Address(a1, length_offset)); + lwu(cnt2, Address(a2, length_offset)); + bne(cnt2, cnt1, DONE); + beqz(cnt1, SAME); + + slli(tmp5, cnt1, 3 + log_elem_size); + sub(tmp5, zr, tmp5); + add(a1, a1, base_offset); + add(a2, a2, base_offset); + ld(tmp3, Address(a1, 0)); + ld(tmp4, Address(a2, 0)); + ble(cnt1, elem_per_word, SHORT); // short or same + + // Main 16 byte comparison loop with 2 exits + bind(NEXT_DWORD); { + ld(tmp1, Address(a1, wordSize)); + ld(tmp2, Address(a2, wordSize)); + sub(cnt1, cnt1, 2 * wordSize / elem_size); + blez(cnt1, TAIL); + bne(tmp3, tmp4, DONE); + ld(tmp3, Address(a1, 2 * wordSize)); + ld(tmp4, Address(a2, 2 * wordSize)); + add(a1, a1, 2 * wordSize); + add(a2, a2, 2 * wordSize); + ble(cnt1, elem_per_word, TAIL2); + } beq(tmp1, tmp2, NEXT_DWORD); + j(DONE); + + bind(TAIL); + xorr(tmp4, tmp3, tmp4); + xorr(tmp2, tmp1, tmp2); + sll(tmp2, tmp2, tmp5); + orr(tmp5, tmp4, tmp2); + j(IS_TMP5_ZR); + + bind(TAIL2); + bne(tmp1, tmp2, DONE); + + bind(SHORT); + xorr(tmp4, tmp3, tmp4); + sll(tmp5, tmp4, tmp5); + + bind(IS_TMP5_ZR); + bnez(tmp5, DONE); + + bind(SAME); + mv(result, true); + // That's it. + bind(DONE); + + BLOCK_COMMENT("} array_equals"); +} + +// Compare Strings + +// For Strings we're passed the address of the first characters in a1 +// and a2 and the length in cnt1. +// elem_size is the element size in bytes: either 1 or 2. +// There are two implementations. For arrays >= 8 bytes, all +// comparisons (including the final one, which may overlap) are +// performed 8 bytes at a time. For strings < 8 bytes, we compare a +// halfword, then a short, and then a byte. + +void C2_MacroAssembler::string_equals(Register a1, Register a2, + Register result, Register cnt1, int elem_size) +{ + Label SAME, DONE, SHORT, NEXT_WORD; + Register tmp1 = t0; + Register tmp2 = t1; + + assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte"); + assert_different_registers(a1, a2, result, cnt1, t0, t1); + + BLOCK_COMMENT("string_equals {"); + + mv(result, false); + + // Check for short strings, i.e. smaller than wordSize. + sub(cnt1, cnt1, wordSize); + bltz(cnt1, SHORT); + + // Main 8 byte comparison loop. + bind(NEXT_WORD); { + ld(tmp1, Address(a1, 0)); + add(a1, a1, wordSize); + ld(tmp2, Address(a2, 0)); + add(a2, a2, wordSize); + sub(cnt1, cnt1, wordSize); + bne(tmp1, tmp2, DONE); + } bgtz(cnt1, NEXT_WORD); + + // Last longword. In the case where length == 4 we compare the + // same longword twice, but that's still faster than another + // conditional branch. + // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when + // length == 4. + add(tmp1, a1, cnt1); + ld(tmp1, Address(tmp1, 0)); + add(tmp2, a2, cnt1); + ld(tmp2, Address(tmp2, 0)); + bne(tmp1, tmp2, DONE); + j(SAME); + + bind(SHORT); + Label TAIL03, TAIL01; + + // 0-7 bytes left. + andi(t0, cnt1, 4); + beqz(t0, TAIL03); + { + lwu(tmp1, Address(a1, 0)); + add(a1, a1, 4); + lwu(tmp2, Address(a2, 0)); + add(a2, a2, 4); + bne(tmp1, tmp2, DONE); + } + + bind(TAIL03); + // 0-3 bytes left. + andi(t0, cnt1, 2); + beqz(t0, TAIL01); + { + lhu(tmp1, Address(a1, 0)); + add(a1, a1, 2); + lhu(tmp2, Address(a2, 0)); + add(a2, a2, 2); + bne(tmp1, tmp2, DONE); + } + + bind(TAIL01); + if (elem_size == 1) { // Only needed when comparing 1-byte elements + // 0-1 bytes left. + andi(t0, cnt1, 1); + beqz(t0, SAME); + { + lbu(tmp1, a1, 0); + lbu(tmp2, a2, 0); + bne(tmp1, tmp2, DONE); + } + } + + // Arrays are equal. + bind(SAME); + mv(result, true); + + // That's it. + bind(DONE); + BLOCK_COMMENT("} string_equals"); +} + +typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far); +typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label, + bool is_far, bool is_unordered); + +static conditional_branch_insn conditional_branches[] = +{ + /* SHORT branches */ + (conditional_branch_insn)&Assembler::beq, + (conditional_branch_insn)&Assembler::bgt, + NULL, // BoolTest::overflow + (conditional_branch_insn)&Assembler::blt, + (conditional_branch_insn)&Assembler::bne, + (conditional_branch_insn)&Assembler::ble, + NULL, // BoolTest::no_overflow + (conditional_branch_insn)&Assembler::bge, + + /* UNSIGNED branches */ + (conditional_branch_insn)&Assembler::beq, + (conditional_branch_insn)&Assembler::bgtu, + NULL, + (conditional_branch_insn)&Assembler::bltu, + (conditional_branch_insn)&Assembler::bne, + (conditional_branch_insn)&Assembler::bleu, + NULL, + (conditional_branch_insn)&Assembler::bgeu +}; + +static float_conditional_branch_insn float_conditional_branches[] = +{ + /* FLOAT SHORT branches */ + (float_conditional_branch_insn)&MacroAssembler::float_beq, + (float_conditional_branch_insn)&MacroAssembler::float_bgt, + NULL, // BoolTest::overflow + (float_conditional_branch_insn)&MacroAssembler::float_blt, + (float_conditional_branch_insn)&MacroAssembler::float_bne, + (float_conditional_branch_insn)&MacroAssembler::float_ble, + NULL, // BoolTest::no_overflow + (float_conditional_branch_insn)&MacroAssembler::float_bge, + + /* DOUBLE SHORT branches */ + (float_conditional_branch_insn)&MacroAssembler::double_beq, + (float_conditional_branch_insn)&MacroAssembler::double_bgt, + NULL, + (float_conditional_branch_insn)&MacroAssembler::double_blt, + (float_conditional_branch_insn)&MacroAssembler::double_bne, + (float_conditional_branch_insn)&MacroAssembler::double_ble, + NULL, + (float_conditional_branch_insn)&MacroAssembler::double_bge +}; + +void C2_MacroAssembler::cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, bool is_far) { + assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(conditional_branches) / sizeof(conditional_branches[0])), + "invalid conditional branch index"); + (this->*conditional_branches[cmpFlag])(op1, op2, label, is_far); +} + +// This is a function should only be used by C2. Flip the unordered when unordered-greater, C2 would use +// unordered-lesser instead of unordered-greater. Finally, commute the result bits at function do_one_bytecode(). +void C2_MacroAssembler::float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, bool is_far) { + assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(float_conditional_branches) / sizeof(float_conditional_branches[0])), + "invalid float conditional branch index"); + int booltest_flag = cmpFlag & ~(C2_MacroAssembler::double_branch_mask); + (this->*float_conditional_branches[cmpFlag])(op1, op2, label, is_far, + (booltest_flag == (BoolTest::ge) || booltest_flag == (BoolTest::gt)) ? false : true); +} + +void C2_MacroAssembler::enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { + switch (cmpFlag) { + case BoolTest::eq: + case BoolTest::le: + beqz(op1, L, is_far); + break; + case BoolTest::ne: + case BoolTest::gt: + bnez(op1, L, is_far); + break; + default: + ShouldNotReachHere(); + } +} + +void C2_MacroAssembler::enc_cmpEqNe_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { + switch (cmpFlag) { + case BoolTest::eq: + beqz(op1, L, is_far); + break; + case BoolTest::ne: + bnez(op1, L, is_far); + break; + default: + ShouldNotReachHere(); + } +} + +void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Register dst, Register src) { + Label L; + cmp_branch(cmpFlag ^ (1 << neg_cond_bits), op1, op2, L); + mv(dst, src); + bind(L); +} + +// Set dst to NaN if any NaN input. +void C2_MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRegister src2, + bool is_double, bool is_min) { + assert_different_registers(dst, src1, src2); + + Label Done; + fsflags(zr); + if (is_double) { + is_min ? fmin_d(dst, src1, src2) + : fmax_d(dst, src1, src2); + // Checking NaNs + flt_d(zr, src1, src2); + } else { + is_min ? fmin_s(dst, src1, src2) + : fmax_s(dst, src1, src2); + // Checking NaNs + flt_s(zr, src1, src2); + } + + frflags(t0); + beqz(t0, Done); + + // In case of NaNs + is_double ? fadd_d(dst, src1, src2) + : fadd_s(dst, src1, src2); + + bind(Done); +} + +void C2_MacroAssembler::element_compare(Register a1, Register a2, Register result, Register cnt, Register tmp1, Register tmp2, + VectorRegister vr1, VectorRegister vr2, VectorRegister vrs, bool islatin, Label &DONE) { + Label loop; + Assembler::SEW sew = islatin ? Assembler::e8 : Assembler::e16; + + bind(loop); + vsetvli(tmp1, cnt, sew, Assembler::m2); + vlex_v(vr1, a1, sew); + vlex_v(vr2, a2, sew); + vmsne_vv(vrs, vr1, vr2); + vfirst_m(tmp2, vrs); + bgez(tmp2, DONE); + sub(cnt, cnt, tmp1); + if (!islatin) { + slli(tmp1, tmp1, 1); // get byte counts + } + add(a1, a1, tmp1); + add(a2, a2, tmp1); + bnez(cnt, loop); + + mv(result, true); +} + +void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register result, Register cnt, int elem_size) { + Label DONE; + Register tmp1 = t0; + Register tmp2 = t1; + + BLOCK_COMMENT("string_equals_v {"); + + mv(result, false); + + if (elem_size == 2) { + srli(cnt, cnt, 1); + } + + element_compare(a1, a2, result, cnt, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); + + bind(DONE); + BLOCK_COMMENT("} string_equals_v"); +} + +// used by C2 ClearArray patterns. +// base: Address of a buffer to be zeroed +// cnt: Count in HeapWords +// +// base, cnt, v0, v1 and t0 are clobbered. +void C2_MacroAssembler::clear_array_v(Register base, Register cnt) { + Label loop; + + // making zero words + vsetvli(t0, cnt, Assembler::e64, Assembler::m4); + vxor_vv(v0, v0, v0); + + bind(loop); + vsetvli(t0, cnt, Assembler::e64, Assembler::m4); + vse64_v(v0, base); + sub(cnt, cnt, t0); + shadd(base, t0, base, t0, 3); + bnez(cnt, loop); +} + +void C2_MacroAssembler::arrays_equals_v(Register a1, Register a2, Register result, + Register cnt1, int elem_size) { + Label DONE; + Register tmp1 = t0; + Register tmp2 = t1; + Register cnt2 = tmp2; + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); + + BLOCK_COMMENT("arrays_equals_v {"); + + // if (a1 == a2), return true + mv(result, true); + beq(a1, a2, DONE); + + mv(result, false); + // if a1 == null or a2 == null, return false + beqz(a1, DONE); + beqz(a2, DONE); + // if (a1.length != a2.length), return false + lwu(cnt1, Address(a1, length_offset)); + lwu(cnt2, Address(a2, length_offset)); + bne(cnt1, cnt2, DONE); + + la(a1, Address(a1, base_offset)); + la(a2, Address(a2, base_offset)); + + element_compare(a1, a2, result, cnt1, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); + + bind(DONE); + + BLOCK_COMMENT("} arrays_equals_v"); +} + +void C2_MacroAssembler::string_compare_v(Register str1, Register str2, Register cnt1, Register cnt2, + Register result, Register tmp1, Register tmp2, int encForm) { + Label DIFFERENCE, DONE, L, loop; + bool encLL = encForm == StrIntrinsicNode::LL; + bool encLU = encForm == StrIntrinsicNode::LU; + bool encUL = encForm == StrIntrinsicNode::UL; + + bool str1_isL = encLL || encLU; + bool str2_isL = encLL || encUL; + + int minCharsInWord = encLL ? wordSize : wordSize / 2; + + BLOCK_COMMENT("string_compare {"); + + // for Lating strings, 1 byte for 1 character + // for UTF16 strings, 2 bytes for 1 character + if (!str1_isL) + sraiw(cnt1, cnt1, 1); + if (!str2_isL) + sraiw(cnt2, cnt2, 1); + + // if str1 == str2, return the difference + // save the minimum of the string lengths in cnt2. + sub(result, cnt1, cnt2); + bgt(cnt1, cnt2, L); + mv(cnt2, cnt1); + bind(L); + + if (str1_isL == str2_isL) { // LL or UU + element_compare(str1, str2, zr, cnt2, tmp1, tmp2, v2, v4, v1, encLL, DIFFERENCE); + j(DONE); + } else { // LU or UL + Register strL = encLU ? str1 : str2; + Register strU = encLU ? str2 : str1; + VectorRegister vstr1 = encLU ? v4 : v0; + VectorRegister vstr2 = encLU ? v0 : v4; + + bind(loop); + vsetvli(tmp1, cnt2, Assembler::e8, Assembler::m2); + vle8_v(vstr1, strL); + vsetvli(tmp1, cnt2, Assembler::e16, Assembler::m4); + vzext_vf2(vstr2, vstr1); + vle16_v(vstr1, strU); + vmsne_vv(v0, vstr2, vstr1); + vfirst_m(tmp2, v0); + bgez(tmp2, DIFFERENCE); + sub(cnt2, cnt2, tmp1); + add(strL, strL, tmp1); + shadd(strU, tmp1, strU, tmp1, 1); + bnez(cnt2, loop); + j(DONE); + } + bind(DIFFERENCE); + slli(tmp1, tmp2, 1); + add(str1, str1, str1_isL ? tmp2 : tmp1); + add(str2, str2, str2_isL ? tmp2 : tmp1); + str1_isL ? lbu(tmp1, Address(str1, 0)) : lhu(tmp1, Address(str1, 0)); + str2_isL ? lbu(tmp2, Address(str2, 0)) : lhu(tmp2, Address(str2, 0)); + sub(result, tmp1, tmp2); + + bind(DONE); +} + +void C2_MacroAssembler::byte_array_inflate_v(Register src, Register dst, Register len, Register tmp) { + Label loop; + assert_different_registers(src, dst, len, tmp, t0); + + BLOCK_COMMENT("byte_array_inflate_v {"); + bind(loop); + vsetvli(tmp, len, Assembler::e8, Assembler::m2); + vle8_v(v2, src); + vsetvli(t0, len, Assembler::e16, Assembler::m4); + vzext_vf2(v0, v2); + vse16_v(v0, dst); + sub(len, len, tmp); + add(src, src, tmp); + shadd(dst, tmp, dst, tmp, 1); + bnez(len, loop); + BLOCK_COMMENT("} byte_array_inflate_v"); +} + +// Compress char[] array to byte[]. +// result: the array length if every element in array can be encoded; 0, otherwise. +void C2_MacroAssembler::char_array_compress_v(Register src, Register dst, Register len, Register result, Register tmp) { + Label done; + encode_iso_array_v(src, dst, len, result, tmp); + beqz(len, done); + mv(result, zr); + bind(done); +} + +// result: the number of elements had been encoded. +void C2_MacroAssembler::encode_iso_array_v(Register src, Register dst, Register len, Register result, Register tmp) { + Label loop, DIFFERENCE, DONE; + + BLOCK_COMMENT("encode_iso_array_v {"); + mv(result, 0); + + bind(loop); + mv(tmp, 0xff); + vsetvli(t0, len, Assembler::e16, Assembler::m2); + vle16_v(v2, src); + // if element > 0xff, stop + vmsgtu_vx(v1, v2, tmp); + vfirst_m(tmp, v1); + vmsbf_m(v0, v1); + // compress char to byte + vsetvli(t0, len, Assembler::e8); + vncvt_x_x_w(v1, v2, Assembler::v0_t); + vse8_v(v1, dst, Assembler::v0_t); + + bgez(tmp, DIFFERENCE); + add(result, result, t0); + add(dst, dst, t0); + sub(len, len, t0); + shadd(src, t0, src, t0, 1); + bnez(len, loop); + j(DONE); + + bind(DIFFERENCE); + add(result, result, tmp); + + bind(DONE); + BLOCK_COMMENT("} encode_iso_array_v"); +} + +void C2_MacroAssembler::count_positives_v(Register ary, Register len, Register result, Register tmp) { + Label LOOP, SET_RESULT, DONE; + + BLOCK_COMMENT("count_positives_v {"); + mv(result, zr); + + bind(LOOP); + vsetvli(t0, len, Assembler::e8, Assembler::m4); + vle8_v(v0, ary); + vmslt_vx(v0, v0, zr); + vfirst_m(tmp, v0); + bgez(tmp, SET_RESULT); + // if tmp == -1, all bytes are positive + add(result, result, t0); + + sub(len, len, t0); + add(ary, ary, t0); + bnez(len, LOOP); + j(DONE); + + // add remaining positive bytes count + bind(SET_RESULT); + add(result, result, tmp); + + bind(DONE); + BLOCK_COMMENT("} count_positives_v"); +} + +void C2_MacroAssembler::string_indexof_char_v(Register str1, Register cnt1, + Register ch, Register result, + Register tmp1, Register tmp2, + bool isL) { + mv(result, zr); + + Label loop, MATCH, DONE; + Assembler::SEW sew = isL ? Assembler::e8 : Assembler::e16; + bind(loop); + vsetvli(tmp1, cnt1, sew, Assembler::m4); + vlex_v(v0, str1, sew); + vmseq_vx(v0, v0, ch); + vfirst_m(tmp2, v0); + bgez(tmp2, MATCH); // if equal, return index + + add(result, result, tmp1); + sub(cnt1, cnt1, tmp1); + if (!isL) slli(tmp1, tmp1, 1); + add(str1, str1, tmp1); + bnez(cnt1, loop); + + mv(result, -1); + j(DONE); + + bind(MATCH); + add(result, result, tmp2); + + bind(DONE); +} + +// Set dst to NaN if any NaN input. +void C2_MacroAssembler::minmax_FD_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, + bool is_double, bool is_min) { + assert_different_registers(dst, src1, src2); + + vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); + + is_min ? vfmin_vv(dst, src1, src2) + : vfmax_vv(dst, src1, src2); + + vmfne_vv(v0, src1, src1); + vfadd_vv(dst, src1, src1, Assembler::v0_t); + vmfne_vv(v0, src2, src2); + vfadd_vv(dst, src2, src2, Assembler::v0_t); +} + +// Set dst to NaN if any NaN input. +void C2_MacroAssembler::reduce_minmax_FD_v(FloatRegister dst, + FloatRegister src1, VectorRegister src2, + VectorRegister tmp1, VectorRegister tmp2, + bool is_double, bool is_min) { + assert_different_registers(src2, tmp1, tmp2); + + Label L_done, L_NaN; + vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); + vfmv_s_f(tmp2, src1); + + is_min ? vfredmin_vs(tmp1, src2, tmp2) + : vfredmax_vs(tmp1, src2, tmp2); + + fsflags(zr); + // Checking NaNs + vmflt_vf(tmp2, src2, src1); + frflags(t0); + bnez(t0, L_NaN); + j(L_done); + + bind(L_NaN); + vfmv_s_f(tmp2, src1); + vfredsum_vs(tmp1, src2, tmp2); + + bind(L_done); + vfmv_f_s(dst, tmp1); +} diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c71df4c101b664b129c1d6278788d3b1059cfbb6 --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP +#define CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP + +// C2_MacroAssembler contains high-level macros for C2 + + private: + void element_compare(Register r1, Register r2, + Register result, Register cnt, + Register tmp1, Register tmp2, + VectorRegister vr1, VectorRegister vr2, + VectorRegister vrs, + bool is_latin, Label& DONE); + public: + + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, + Register tmp1, Register tmp2, Register tmp3, + int ae); + + void string_indexof_char_short(Register str1, Register cnt1, + Register ch, Register result, + bool isL); + + void string_indexof_char(Register str1, Register cnt1, + Register ch, Register result, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + bool isL); + + void string_indexof(Register str1, Register str2, + Register cnt1, Register cnt2, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + Register tmp5, Register tmp6, + Register result, int ae); + + void string_indexof_linearscan(Register haystack, Register needle, + Register haystack_len, Register needle_len, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + int needle_con_cnt, Register result, int ae); + + void arrays_equals(Register r1, Register r2, + Register tmp3, Register tmp4, + Register tmp5, Register tmp6, + Register result, Register cnt1, + int elem_size); + + void string_equals(Register r1, Register r2, + Register result, Register cnt1, + int elem_size); + + // refer to conditional_branches and float_conditional_branches + static const int bool_test_bits = 3; + static const int neg_cond_bits = 2; + static const int unsigned_branch_mask = 1 << bool_test_bits; + static const int double_branch_mask = 1 << bool_test_bits; + + // cmp + void cmp_branch(int cmpFlag, + Register op1, Register op2, + Label& label, bool is_far = false); + + void float_cmp_branch(int cmpFlag, + FloatRegister op1, FloatRegister op2, + Label& label, bool is_far = false); + + void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, + Label& L, bool is_far = false); + + void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, + Label& L, bool is_far = false); + + void enc_cmove(int cmpFlag, + Register op1, Register op2, + Register dst, Register src); + + void spill(Register r, bool is64, int offset) { + is64 ? sd(r, Address(sp, offset)) + : sw(r, Address(sp, offset)); + } + + void spill(FloatRegister f, bool is64, int offset) { + is64 ? fsd(f, Address(sp, offset)) + : fsw(f, Address(sp, offset)); + } + + void spill(VectorRegister v, int offset) { + add(t0, sp, offset); + vs1r_v(v, t0); + } + + void unspill(Register r, bool is64, int offset) { + is64 ? ld(r, Address(sp, offset)) + : lw(r, Address(sp, offset)); + } + + void unspillu(Register r, bool is64, int offset) { + is64 ? ld(r, Address(sp, offset)) + : lwu(r, Address(sp, offset)); + } + + void unspill(FloatRegister f, bool is64, int offset) { + is64 ? fld(f, Address(sp, offset)) + : flw(f, Address(sp, offset)); + } + + void unspill(VectorRegister v, int offset) { + add(t0, sp, offset); + vl1r_v(v, t0); + } + + void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, int vec_reg_size_in_bytes) { + assert(vec_reg_size_in_bytes % 16 == 0, "unexpected vector reg size"); + unspill(v0, src_offset); + spill(v0, dst_offset); + } + + void minmax_FD(FloatRegister dst, + FloatRegister src1, FloatRegister src2, + bool is_double, bool is_min); + + // intrinsic methods implemented by rvv instructions + void string_equals_v(Register r1, Register r2, + Register result, Register cnt1, + int elem_size); + + void arrays_equals_v(Register r1, Register r2, + Register result, Register cnt1, + int elem_size); + + void string_compare_v(Register str1, Register str2, + Register cnt1, Register cnt2, + Register result, + Register tmp1, Register tmp2, + int encForm); + + void clear_array_v(Register base, Register cnt); + + void byte_array_inflate_v(Register src, Register dst, + Register len, Register tmp); + + void char_array_compress_v(Register src, Register dst, + Register len, Register result, + Register tmp); + + void encode_iso_array_v(Register src, Register dst, + Register len, Register result, + Register tmp); + + void count_positives_v(Register ary, Register len, + Register result, Register tmp); + + void string_indexof_char_v(Register str1, Register cnt1, + Register ch, Register result, + Register tmp1, Register tmp2, + bool isL); + + void minmax_FD_v(VectorRegister dst, + VectorRegister src1, VectorRegister src2, + bool is_double, bool is_min); + + void reduce_minmax_FD_v(FloatRegister dst, + FloatRegister src1, VectorRegister src2, + VectorRegister tmp1, VectorRegister tmp2, + bool is_double, bool is_min); + +#endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..53a41665f4b8e5b17442c99f51b2cb66b2b9d6fc --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_C2_GLOBALS_RISCV_HPP +#define CPU_RISCV_C2_GLOBALS_RISCV_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the server compiler. +// (see c2_globals.hpp). Alpha-sorted. + +define_pd_global(bool, BackgroundCompilation, true); +define_pd_global(bool, CICompileOSR, true); +define_pd_global(bool, InlineIntrinsics, true); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, true); +define_pd_global(bool, UseOnStackReplacement, true); +define_pd_global(bool, ProfileInterpreter, true); +define_pd_global(bool, TieredCompilation, COMPILER1_PRESENT(true) NOT_COMPILER1(false)); +define_pd_global(intx, CompileThreshold, 10000); + +define_pd_global(intx, OnStackReplacePercentage, 140); +define_pd_global(intx, ConditionalMoveLimit, 0); +define_pd_global(intx, FreqInlineSize, 325); +define_pd_global(intx, MinJumpTableSize, 10); +define_pd_global(intx, InteriorEntryAlignment, 16); +define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); +define_pd_global(intx, LoopUnrollLimit, 60); +define_pd_global(intx, LoopPercentProfileLimit, 10); +// InitialCodeCacheSize derived from specjbb2000 run. +define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(intx, CodeCacheExpansionSize, 64*K); + +// Ergonomics related flags +define_pd_global(uint64_t,MaxRAM, 128ULL*G); +define_pd_global(intx, RegisterCostAreaRatio, 16000); + +// Peephole and CISC spilling both break the graph, and so makes the +// scheduler sick. +define_pd_global(bool, OptoPeephole, false); +define_pd_global(bool, UseCISCSpill, false); +define_pd_global(bool, OptoScheduling, true); +define_pd_global(bool, OptoBundling, false); +define_pd_global(bool, OptoRegScheduling, false); +define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(bool, IdealizeClearArrayNode, true); + +define_pd_global(intx, ReservedCodeCacheSize, 48*M); +define_pd_global(intx, NonProfiledCodeHeapSize, 21*M); +define_pd_global(intx, ProfiledCodeHeapSize, 22*M); +define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(uintx, CodeCacheMinBlockLength, 6); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); + +// Ergonomics related flags +define_pd_global(bool, NeverActAsServerClassMachine, false); + +define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed. + +#endif // CPU_RISCV_C2_GLOBALS_RISCV_HPP diff --git a/src/java.base/windows/native/libnet/InetAddressImplFactory.c b/src/hotspot/cpu/riscv/c2_init_riscv.cpp similarity index 58% rename from src/java.base/windows/native/libnet/InetAddressImplFactory.c rename to src/hotspot/cpu/riscv/c2_init_riscv.cpp index 9d76762ca6cfeeb5ce78c5064e53c67924b93ffa..cdbd69807bee18aeedebb24a29cdae2126b8b4b5 100644 --- a/src/java.base/windows/native/libnet/InetAddressImplFactory.c +++ b/src/hotspot/cpu/riscv/c2_init_riscv.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -21,26 +21,18 @@ * Please 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 "java_net_InetAddressImplFactory.h" -#include "net_util.h" -/* - * InetAddressImplFactory - */ +#include "precompiled.hpp" +#include "opto/compile.hpp" +#include "opto/node.hpp" +// processor dependent initialization for riscv -/* - * Class: java_net_InetAddressImplFactory - * Method: isIPv6Supported - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL -Java_java_net_InetAddressImplFactory_isIPv6Supported(JNIEnv *env, jobject this) -{ - if (ipv6_available()) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } +extern void reg_mask_init(); + +void Compile::pd_compiler2_init() { + guarantee(CodeEntryAlignment >= InteriorEntryAlignment, "" ); + reg_mask_init(); } diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a90d9fdc160a5e293bda77977adaf79fc0a680e6 --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "opto/compile.hpp" +#include "opto/node.hpp" +#include "opto/output.hpp" +#include "runtime/sharedRuntime.hpp" + +#define __ masm. +void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + assert(SharedRuntime::polling_page_return_handler_blob() != NULL, + "polling page return stub not created yet"); + address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); + RuntimeAddress callback_addr(stub); + + __ bind(entry->_stub_label); + InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); + masm.code_section()->relocate(masm.pc(), safepoint_pc.rspec()); + __ la(t0, safepoint_pc.target()); + __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); + __ far_jump(callback_addr); +} +#undef __ diff --git a/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..14a68b45026da4349ecaea744c6b0b83f456a71f --- /dev/null +++ b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_CODEBUFFER_RISCV_HPP +#define CPU_RISCV_CODEBUFFER_RISCV_HPP + +private: + void pd_initialize() {} + +public: + void flush_bundle(bool start_new_bundle) {} + +#endif // CPU_RISCV_CODEBUFFER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75bc4be7840991d5896edf041d1ab44d05a0210c --- /dev/null +++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" +#include "code/icBuffer.hpp" +#include "code/nmethod.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/safepoint.hpp" + +// ---------------------------------------------------------------------------- + +#define __ _masm. +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { + precond(cbuf.stubs()->start() != badAddress); + precond(cbuf.stubs()->end() != badAddress); + // Stub is fixed up when the corresponding call is converted from + // calling compiled code to calling interpreted code. + // mv xmethod, 0 + // jalr -4 # to self + + if (mark == NULL) { + mark = cbuf.insts_mark(); // Get mark within main instrs section. + } + + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a stub. + MacroAssembler _masm(&cbuf); + + address base = __ start_a_stub(to_interp_stub_size()); + int offset = __ offset(); + if (base == NULL) { + return NULL; // CodeBuffer::expand failed + } + // static stub relocation stores the instruction address of the call + __ relocate(static_stub_Relocation::spec(mark)); + + __ emit_static_call_stub(); + + assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big"); + __ end_a_stub(); + return base; +} +#undef __ + +int CompiledStaticCall::to_interp_stub_size() { + // fence_i + fence* + (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr + return NativeFenceI::instruction_size() + 12 * NativeInstruction::instruction_size; +} + +int CompiledStaticCall::to_trampoline_stub_size() { + // Somewhat pessimistically, we count 4 instructions here (although + // there are only 3) because we sometimes emit an alignment nop. + // Trampoline stubs are always word aligned. + return NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size; +} + +// Relocation entries for call stub, compiled java to interpreter. +int CompiledStaticCall::reloc_to_interp_stub() { + return 4; // 3 in emit_to_interp_stub + 1 in emit_call +} + +void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { + address stub = find_stub(); + guarantee(stub != NULL, "stub not found"); + + if (TraceICs) { + ResourceMark rm; + tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", + p2i(instruction_address()), + callee->name_and_sig_as_C_string()); + } + + // Creation also verifies the object. + NativeMovConstReg* method_holder + = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); +#ifdef ASSERT + NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); + + verify_mt_safe(callee, entry, method_holder, jump); +#endif + // Update stub. + method_holder->set_data((intptr_t)callee()); + NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry); + ICache::invalidate_range(stub, to_interp_stub_size()); + // Update jump to call. + set_destination_mt_safe(stub); +} + +void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { + // Reset stub. + address stub = static_stub->addr(); + assert(stub != NULL, "stub not found"); + assert(CompiledICLocker::is_safe(stub), "mt unsafe call"); + // Creation also verifies the object. + NativeMovConstReg* method_holder + = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); + method_holder->set_data(0); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + jump->set_jump_destination((address)-1); +} + +//----------------------------------------------------------------------------- +// Non-product mode code +#ifndef PRODUCT + +void CompiledDirectStaticCall::verify() { + // Verify call. + _call->verify(); + _call->verify_alignment(); + + // Verify stub. + address stub = find_stub(); + assert(stub != NULL, "no stub found for static call"); + // Creation also verifies the object. + NativeMovConstReg* method_holder + = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + + // Verify state. + assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); +} + +#endif // !PRODUCT diff --git a/src/hotspot/cpu/riscv/copy_riscv.hpp b/src/hotspot/cpu/riscv/copy_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bceadcc5dcc1cbc03f97541c0a0d2b652eac5070 --- /dev/null +++ b/src/hotspot/cpu/riscv/copy_riscv.hpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_COPY_RISCV_HPP +#define CPU_RISCV_COPY_RISCV_HPP + +#include OS_CPU_HEADER(copy) + +static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { + julong* to = (julong*) tohw; + julong v = ((julong) value << 32) | value; + while (count-- > 0) { + *to++ = v; + } +} + +static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { + pd_fill_to_words(tohw, count, value); +} + +static void pd_fill_to_bytes(void* to, size_t count, jubyte value) { + (void)memset(to, value, count); +} + +static void pd_zero_to_words(HeapWord* tohw, size_t count) { + pd_fill_to_words(tohw, count, 0); +} + +static void pd_zero_to_bytes(void* to, size_t count) { + (void)memset(to, 0, count); +} + +static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + (void)memmove(to, from, count * HeapWordSize); +} + +static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + switch (count) { + case 8: to[7] = from[7]; // fall through + case 7: to[6] = from[6]; // fall through + case 6: to[5] = from[5]; // fall through + case 5: to[4] = from[4]; // fall through + case 4: to[3] = from[3]; // fall through + case 3: to[2] = from[2]; // fall through + case 2: to[1] = from[1]; // fall through + case 1: to[0] = from[0]; // fall through + case 0: break; + default: + memcpy(to, from, count * HeapWordSize); + break; + } +} + +static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { + shared_disjoint_words_atomic(from, to, count); +} + +static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_words(from, to, count); +} + +static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(const void* from, void* to, size_t count) { + (void)memmove(to, from, count); +} + +static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { + pd_conjoint_bytes(from, to, count); +} + +static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { + _Copy_conjoint_jshorts_atomic(from, to, count); +} + +static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { + _Copy_conjoint_jints_atomic(from, to, count); +} + +static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { + _Copy_conjoint_jlongs_atomic(from, to, count); +} + +static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size."); + _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); +} + +static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_bytes(from, to, count); +} + +static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jshorts(from, to, count); +} + +static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jints(from, to, count); +} + +static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jlongs(from, to, count); +} + +static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { + assert(!UseCompressedOops, "foo!"); + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_arrayof_conjoint_jlongs(from, to, count); +} + +#endif // CPU_RISCV_COPY_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/disassembler_riscv.hpp b/src/hotspot/cpu/riscv/disassembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0e5560c9064f502d8e4a8760d88f119ee4520fb --- /dev/null +++ b/src/hotspot/cpu/riscv/disassembler_riscv.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_DISASSEMBLER_RISCV_HPP +#define CPU_RISCV_DISASSEMBLER_RISCV_HPP + +static int pd_instruction_alignment() { + return 1; +} + +static const char* pd_cpu_opts() { + return ""; +} + +// Returns address of n-th instruction preceding addr, +// NULL if no preceding instruction can be found. +// On riscv, we assume a constant instruction length. +// It might be beneficial to check "is_readable" as we do on ppc and s390. +static address find_prev_instr(address addr, int n_instr) { + return addr - Assembler::instruction_size * n_instr; +} + +// special-case instruction decoding. +// There may be cases where the binutils disassembler doesn't do +// the perfect job. In those cases, decode_instruction0 may kick in +// and do it right. +// If nothing had to be done, just return "here", otherwise return "here + instr_len(here)" +static address decode_instruction0(address here, outputStream* st, address virtual_begin = NULL) { + return here; +} + +// platform-specific instruction annotations (like value of loaded constants) +static void annotate(address pc, outputStream* st) {} + +#endif // CPU_RISCV_DISASSEMBLER_RISCV_HPP diff --git a/test/jdk/sun/net/www/httptest/HttpCallback.java b/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp similarity index 57% rename from test/jdk/sun/net/www/httptest/HttpCallback.java rename to src/hotspot/cpu/riscv/foreign_globals_riscv.cpp index 27af7b7aaf4ebbbe7cfec599d20305ec526db8ed..5c700be9c91cc1f9599d70c8c04cc117e7129c77 100644 --- a/test/jdk/sun/net/www/httptest/HttpCallback.java +++ b/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,21 +20,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. + * */ -/** - * 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. - */ -public interface HttpCallback { - /** - * 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 - */ - void request (HttpTransaction msg); +#include "precompiled.hpp" +#include "prims/foreign_globals.hpp" +#include "utilities/debug.hpp" + +// Stubbed out, implement later +const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const { + Unimplemented(); + return {}; +} + +const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) const { + Unimplemented(); + return {}; +} + +const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const { + ShouldNotCallThis(); + return {}; } diff --git a/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp b/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3ac89752c27eeeac527737d30b2140fcfbe8ed7e --- /dev/null +++ b/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP +#define CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP + +class ABIDescriptor {}; +class BufferLayout {}; + +#endif // CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e38960598a7a620828058a59ca6d15b78c403de --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -0,0 +1,697 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "compiler/oopMap.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" +#include "oops/markWord.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/monitorChunk.hpp" +#include "runtime/os.inline.hpp" +#include "runtime/signature.hpp" +#include "runtime/stackWatermarkSet.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/stubRoutines.hpp" +#include "vmreg_riscv.inline.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#include "runtime/vframeArray.hpp" +#endif + +#ifdef ASSERT +void RegisterMap::check_location_valid() { +} +#endif + + +// Profiling/safepoint support + +bool frame::safe_for_sender(JavaThread *thread) { + address addr_sp = (address)_sp; + address addr_fp = (address)_fp; + address unextended_sp = (address)_unextended_sp; + + // consider stack guards when trying to determine "safe" stack pointers + // sp must be within the usable part of the stack (not in guards) + if (!thread->is_in_usable_stack(addr_sp)) { + return false; + } + + // When we are running interpreted code the machine stack pointer, SP, is + // set low enough so that the Java expression stack can grow and shrink + // without ever exceeding the machine stack bounds. So, ESP >= SP. + + // When we call out of an interpreted method, SP is incremented so that + // the space between SP and ESP is removed. The SP saved in the callee's + // frame is the SP *before* this increment. So, when we walk a stack of + // interpreter frames the sender's SP saved in a frame might be less than + // the SP at the point of call. + + // So unextended sp must be within the stack but we need not to check + // that unextended sp >= sp + + if (!thread->is_in_full_stack_checked(unextended_sp)) { + return false; + } + + // an fp must be within the stack and above (but not equal) sp + // second evaluation on fp+ is added to handle situation where fp is -1 + bool fp_safe = thread->is_in_stack_range_excl(addr_fp, addr_sp) && + thread->is_in_full_stack_checked(addr_fp + (return_addr_offset * sizeof(void*))); + + // We know sp/unextended_sp are safe only fp is questionable here + + // If the current frame is known to the code cache then we can attempt to + // to construct the sender and do some validation of it. This goes a long way + // toward eliminating issues when we get in frame construction code + + if (_cb != NULL) { + + // First check if frame is complete and tester is reliable + // Unfortunately we can only check frame complete for runtime stubs and nmethod + // other generic buffer blobs are more problematic so we just assume they are + // ok. adapter blobs never have a frame complete and are never ok. + + if (!_cb->is_frame_complete_at(_pc)) { + if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { + return false; + } + } + + // Could just be some random pointer within the codeBlob + if (!_cb->code_contains(_pc)) { + return false; + } + + // Entry frame checks + if (is_entry_frame()) { + // an entry frame must have a valid fp. + return fp_safe && is_entry_frame_valid(thread); + } + + intptr_t* sender_sp = NULL; + intptr_t* sender_unextended_sp = NULL; + address sender_pc = NULL; + intptr_t* saved_fp = NULL; + + if (is_interpreted_frame()) { + // fp must be safe + if (!fp_safe) { + 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]; + } else { + // must be some sort of compiled/runtime frame + // fp does not have to be safe (although it could be check for c1?) + + // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc + if (_cb->frame_size() <= 0) { + return false; + } + + sender_sp = _unextended_sp + _cb->frame_size(); + // Is sender_sp safe? + if (!thread->is_in_full_stack_checked((address)sender_sp)) { + return false; + } + + sender_unextended_sp = sender_sp; + sender_pc = (address) *(sender_sp - 1); + saved_fp = (intptr_t*) *(sender_sp - 2); + } + + + // If the potential sender is the interpreter then we can do some more checking + if (Interpreter::contains(sender_pc)) { + + // fp is always saved in a recognizable place in any code we generate. However + // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved fp + // is really a frame pointer. + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { + return false; + } + + // construct the potential sender + frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc); + + return sender.is_interpreted_frame_valid(thread); + } + + // We must always be able to find a recognizable pc + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_pc == NULL || sender_blob == NULL) { + return false; + } + + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + + // Could just be some random pointer within the codeBlob + if (!sender_blob->code_contains(sender_pc)) { + return false; + } + + // We should never be able to see an adapter if the current frame is something from code cache + if (sender_blob->is_adapter_blob()) { + return false; + } + + // Could be the call_stub + if (StubRoutines::returns_to_call_stub(sender_pc)) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { + return false; + } + + // construct the potential sender + frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc); + + // Validate the JavaCallWrapper an entry frame must have + address jcw = (address)sender.entry_frame_call_wrapper(); + + bool jcw_safe = (jcw < thread->stack_base()) && (jcw > (address)sender.fp()); + + return jcw_safe; + } + + CompiledMethod* nm = sender_blob->as_compiled_method_or_null(); + if (nm != NULL) { + if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) || + nm->method()->is_method_handle_intrinsic()) { + return false; + } + } + + // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size + // because the return address counts against the callee's frame. + if (sender_blob->frame_size() <= 0) { + assert(!sender_blob->is_compiled(), "should count return address at least"); + return false; + } + + // We should never be able to see anything here except an nmethod. If something in the + // code cache (current frame) is called by an entity within the code cache that entity + // should not be anything but the call stub (already covered), the interpreter (already covered) + // or an nmethod. + if (!sender_blob->is_compiled()) { + return false; + } + + // Could put some more validation for the potential non-interpreted sender + // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... + + // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb + + // We've validated the potential sender that would be created + return true; + } + + // Must be native-compiled frame. Since sender will try and use fp to find + // linkages it must be safe + if (!fp_safe) { + return false; + } + + // Will the pc we fetch be non-zero (which we'll find at the oldest frame) + if ((address)this->fp()[return_addr_offset] == NULL) { return false; } + + return true; +} + +void frame::patch_pc(Thread* thread, address pc) { + assert(_cb == CodeCache::find_blob(pc), "unexpected pc"); + address* pc_addr = &(((address*) sp())[-1]); + if (TracePcPatching) { + tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]", + p2i(pc_addr), p2i(*pc_addr), p2i(pc)); + } + // 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; + 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"); + _deopt_state = is_deoptimized; + // leave _pc as is + } else { + _deopt_state = not_deoptimized; + _pc = pc; + } +} + +bool frame::is_interpreted_frame() const { + return Interpreter::contains(pc()); +} + +int frame::frame_size(RegisterMap* map) const { + frame sender = this->sender(map); + return sender.sp() - sp(); +} + +intptr_t* frame::entry_frame_argument_at(int offset) const { + // convert offset to index to deal with tsi + int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize); + // Entry frame's arguments are always in relation to unextended_sp() + return &unextended_sp()[index]; +} + +// sender_sp +intptr_t* frame::interpreter_frame_sender_sp() const { + assert(is_interpreted_frame(), "interpreted frame expected"); + return (intptr_t*) at(interpreter_frame_sender_sp_offset); +} + +void frame::set_interpreter_frame_sender_sp(intptr_t* sender_sp) { + assert(is_interpreted_frame(), "interpreted frame expected"); + ptr_at_put(interpreter_frame_sender_sp_offset, (intptr_t) sender_sp); +} + + +// monitor elements + +BasicObjectLock* frame::interpreter_frame_monitor_begin() const { + return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset); +} + +BasicObjectLock* frame::interpreter_frame_monitor_end() const { + BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset); + // make sure the pointer points inside the frame + assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer"); + assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer"); + return result; +} + +void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { + *((BasicObjectLock**)addr_at(interpreter_frame_monitor_block_top_offset)) = value; +} + +// Used by template based interpreter deoptimization +void frame::interpreter_frame_set_last_sp(intptr_t* last_sp) { + *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = last_sp; +} + +frame frame::sender_for_entry_frame(RegisterMap* map) const { + assert(map != NULL, "map must be set"); + // Java frame called from C; skip all C frames and return top C + // frame of that chunk as the sender + JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor(); + assert(!entry_frame_is_first(), "next Java fp must be non zero"); + assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack"); + // Since we are walking the stack now this nested anchor is obviously walkable + // even if it wasn't when it was stacked. + if (!jfa->walkable()) { + // Capture _last_Java_pc (if needed) and mark anchor walkable. + jfa->capture_last_Java_pc(); + } + map->clear(); + assert(map->include_argument_oops(), "should be set by clear"); + vmassert(jfa->last_Java_pc() != NULL, "not walkable"); + frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); + return fr; +} + +OptimizedEntryBlob::FrameData* OptimizedEntryBlob::frame_data_for_frame(const frame& frame) const { + ShouldNotCallThis(); + return nullptr; +} + +bool frame::optimized_entry_frame_is_first() const { + ShouldNotCallThis(); + return false; +} + +frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const { + ShouldNotCallThis(); + return {}; +} + +//------------------------------------------------------------------------------ +// frame::verify_deopt_original_pc +// +// Verifies the calculated original PC of a deoptimization PC for the +// given unextended SP. +#ifdef ASSERT +void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp) { + frame fr; + + // This is ugly but it's better than to change {get,set}_original_pc + // to take an SP value as argument. And it's only a debugging + // method anyway. + fr._unextended_sp = unextended_sp; + + assert_cond(nm != NULL); + address original_pc = nm->get_original_pc(&fr); + assert(nm->insts_contains_inclusive(original_pc), + "original PC must be in the main code section of the the compiled method (or must be immediately following it)"); +} +#endif + +//------------------------------------------------------------------------------ +// frame::adjust_unextended_sp +void frame::adjust_unextended_sp() { + // On riscv, sites calling method handle intrinsics and lambda forms are treated + // as any other call site. Therefore, no special action is needed when we are + // returning to any of these call sites. + + if (_cb != NULL) { + CompiledMethod* sender_cm = _cb->as_compiled_method_or_null(); + if (sender_cm != NULL) { + // If the sender PC is a deoptimization point, get the original PC. + if (sender_cm->is_deopt_entry(_pc) || + sender_cm->is_deopt_mh_entry(_pc)) { + DEBUG_ONLY(verify_deopt_original_pc(sender_cm, _unextended_sp)); + } + } + } +} + +//------------------------------------------------------------------------------ +// frame::update_map_with_saved_link +void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) { + // The interpreter and compiler(s) always save fp in a known + // location on entry. We must record where that location is + // so that if fp was live on callout from c2 we can find + // the saved copy no matter what it called. + + // Since the interpreter always saves fp if we record where it is then + // we don't have to always save fp on entry and exit to c2 compiled + // code, on entry will be enough. + assert(map != NULL, "map must be set"); + map->set_location(::fp->as_VMReg(), (address) link_addr); + // this is weird "H" ought to be at a higher address however the + // oopMaps seems to have the "H" regs at the same address and the + // vanilla register. + map->set_location(::fp->as_VMReg()->next(), (address) link_addr); +} + + +//------------------------------------------------------------------------------ +// frame::sender_for_interpreter_frame +frame frame::sender_for_interpreter_frame(RegisterMap* map) const { + // SP is the raw SP from the sender after adapter or interpreter + // extension. + intptr_t* sender_sp = this->sender_sp(); + + // This is the sp before any possible extension (adapter/locals). + intptr_t* unextended_sp = interpreter_frame_sender_sp(); + +#ifdef COMPILER2 + assert(map != NULL, "map must be set"); + if (map->update_map()) { + update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset)); + } +#endif // COMPILER2 + + return frame(sender_sp, unextended_sp, link(), sender_pc()); +} + + +//------------------------------------------------------------------------------ +// frame::sender_for_compiled_frame +frame frame::sender_for_compiled_frame(RegisterMap* map) const { + // we cannot rely upon the last fp having been saved to the thread + // in C2 code but it will have been pushed onto the stack. so we + // have to find it relative to the unextended sp + + assert(_cb->frame_size() >= 0, "must have non-zero frame size"); + intptr_t* l_sender_sp = unextended_sp() + _cb->frame_size(); + intptr_t* unextended_sp = l_sender_sp; + + // the return_address is always the word on the stack + address sender_pc = (address) *(l_sender_sp + frame::return_addr_offset); + + intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp + frame::link_offset); + + assert(map != NULL, "map must be set"); + if (map->update_map()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. + map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread())); + if (_cb->oop_maps() != NULL) { + OopMapSet::update_register_map(this, map); + } + + // Since the prolog does the save and restore of FP there is no + // oopmap for it so we must fill in its location as if there was + // an oopmap entry since if our caller was compiled code there + // could be live jvm state in it. + update_map_with_saved_link(map, saved_fp_addr); + } + + return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc); +} + +//------------------------------------------------------------------------------ +// frame::sender_raw +frame frame::sender_raw(RegisterMap* map) const { + // Default is we done have to follow them. The sender_for_xxx will + // update it accordingly + assert(map != NULL, "map must be set"); + map->set_include_argument_oops(false); + + if (is_entry_frame()) { + return sender_for_entry_frame(map); + } + if (is_interpreted_frame()) { + return sender_for_interpreter_frame(map); + } + assert(_cb == CodeCache::find_blob(pc()),"Must be the same"); + + // This test looks odd: why is it not is_compiled_frame() ? That's + // because stubs also have OOP maps. + if (_cb != NULL) { + return sender_for_compiled_frame(map); + } + + // Must be native-compiled frame, i.e. the marshaling code for native + // methods that exists in the core system. + return frame(sender_sp(), link(), sender_pc()); +} + +frame frame::sender(RegisterMap* map) const { + frame result = sender_raw(map); + + if (map->process_frames()) { + StackWatermarkSet::on_iteration(map->thread(), result); + } + + return result; +} + +bool frame::is_interpreted_frame_valid(JavaThread* thread) const { + assert(is_interpreted_frame(), "Not an interpreted frame"); + // These are reasonable sanity checks + if (fp() == NULL || (intptr_t(fp()) & (wordSize-1)) != 0) { + return false; + } + if (sp() == NULL || (intptr_t(sp()) & (wordSize-1)) != 0) { + return false; + } + if (fp() + interpreter_frame_initial_sp_offset < sp()) { + return false; + } + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (fp() <= sp()) { // this attempts to deal with unsigned comparison above + return false; + } + + // do some validation of frame elements + + // first the method + Method* m = *interpreter_frame_method_addr(); + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) { + return false; + } + + // stack frames shouldn't be much larger than max_stack elements + // this test requires the use of unextended_sp which is the sp as seen by + // the current frame, and not sp which is the "raw" pc which could point + // further because of local variables of the callee method inserted after + // method arguments + if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { + return false; + } + + // validate bci/bcx + address bcp = interpreter_frame_bcp(); + if (m->validate_bci_from_bcp(bcp) < 0) { + return false; + } + + // validate constantPoolCache* + ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + if (MetaspaceObj::is_valid(cp) == false) { + return false; + } + + // validate locals + address locals = (address) *interpreter_frame_locals_addr(); + if (locals > thread->stack_base() || locals < (address) fp()) { + return false; + } + + // We'd have to be pretty unlucky to be mislead at this point + return true; +} + +BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { + assert(is_interpreted_frame(), "interpreted frame expected"); + Method* method = interpreter_frame_method(); + BasicType type = method->result_type(); + + intptr_t* tos_addr = NULL; + if (method->is_native()) { + tos_addr = (intptr_t*)sp(); + if (type == T_FLOAT || type == T_DOUBLE) { + // This is because we do a push(ltos) after push(dtos) in generate_native_entry. + tos_addr += 2 * Interpreter::stackElementWords; + } + } else { + tos_addr = (intptr_t*)interpreter_frame_tos_address(); + } + + switch (type) { + case T_OBJECT : + case T_ARRAY : { + oop obj; + if (method->is_native()) { + obj = cast_to_oop(at(interpreter_frame_oop_temp_offset)); + } else { + oop* obj_p = (oop*)tos_addr; + obj = (obj_p == NULL) ? (oop)NULL : *obj_p; + } + assert(Universe::is_in_heap_or_null(obj), "sanity check"); + *oop_result = obj; + break; + } + case T_BOOLEAN : value_result->z = *(jboolean*)tos_addr; break; + case T_BYTE : value_result->b = *(jbyte*)tos_addr; break; + case T_CHAR : value_result->c = *(jchar*)tos_addr; break; + case T_SHORT : value_result->s = *(jshort*)tos_addr; break; + case T_INT : value_result->i = *(jint*)tos_addr; break; + case T_LONG : value_result->j = *(jlong*)tos_addr; break; + case T_FLOAT : { + value_result->f = *(jfloat*)tos_addr; + break; + } + case T_DOUBLE : value_result->d = *(jdouble*)tos_addr; break; + case T_VOID : /* Nothing to do */ break; + default : ShouldNotReachHere(); + } + + return type; +} + + +intptr_t* frame::interpreter_frame_tos_at(jint offset) const { + int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize); + return &interpreter_frame_tos_address()[index]; +} + +#ifndef PRODUCT + +#define DESCRIBE_FP_OFFSET(name) \ + values.describe(frame_no, fp() + frame::name##_offset, #name) + +void frame::describe_pd(FrameValues& values, int frame_no) { + if (is_interpreted_frame()) { + DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp); + DESCRIBE_FP_OFFSET(interpreter_frame_last_sp); + DESCRIBE_FP_OFFSET(interpreter_frame_method); + DESCRIBE_FP_OFFSET(interpreter_frame_mdp); + DESCRIBE_FP_OFFSET(interpreter_frame_mirror); + DESCRIBE_FP_OFFSET(interpreter_frame_cache); + DESCRIBE_FP_OFFSET(interpreter_frame_locals); + DESCRIBE_FP_OFFSET(interpreter_frame_bcp); + DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp); + } +} +#endif + +intptr_t *frame::initial_deoptimization_info() { + // Not used on riscv, but we must return something. + return NULL; +} + +intptr_t* frame::real_fp() const { + if (_cb != NULL) { + // use the frame size if valid + int size = _cb->frame_size(); + if (size > 0) { + return unextended_sp() + size; + } + } + // else rely on fp() + assert(!is_compiled_frame(), "unknown compiled frame size"); + return fp(); +} + +#undef DESCRIBE_FP_OFFSET + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* ptr_sp, void* ptr_fp, void* pc) { + init((intptr_t*)ptr_sp, (intptr_t*)ptr_fp, (address)pc); +} + +#endif + +void JavaFrameAnchor::make_walkable(JavaThread* thread) { + // last frame set? + if (last_Java_sp() == NULL) { return; } + // already walkable? + if (walkable()) { return; } + vmassert(Thread::current() == (Thread*)thread, "not current thread"); + vmassert(last_Java_sp() != NULL, "not called from Java code?"); + vmassert(last_Java_pc() == NULL, "already walkable"); + capture_last_Java_pc(); + vmassert(walkable(), "something went wrong"); +} + +void JavaFrameAnchor::capture_last_Java_pc() { + vmassert(_last_Java_sp != NULL, "no last frame set"); + vmassert(_last_Java_pc == NULL, "already walkable"); + _last_Java_pc = (address)_last_Java_sp[-1]; +} diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c06aaa9e391b439bd1bf8f91dba05c74592a9c4a --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.hpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_FRAME_RISCV_HPP +#define CPU_RISCV_FRAME_RISCV_HPP + +#include "runtime/synchronizer.hpp" + +// A frame represents a physical stack frame (an activation). Frames can be +// C or Java frames, and the Java frames can be interpreted or compiled. +// In contrast, vframes represent source-level activations, so that one physical frame +// can correspond to multiple source level frames because of inlining. +// A frame is comprised of {pc, fp, sp} +// ------------------------------ Asm interpreter ---------------------------------------- +// Layout of asm interpreter frame: +// [expression stack ] * <- sp + +// [monitors[0] ] \ +// ... | monitor block size = k +// [monitors[k-1] ] / +// [frame initial esp ] ( == &monitors[0], initially here) initial_sp_offset +// [byte code index/pointr] = bcx() bcx_offset + +// [pointer to locals ] = locals() locals_offset +// [constant pool cache ] = cache() cache_offset + +// [klass of method ] = mirror() mirror_offset +// [padding ] + +// [methodData ] = mdp() mdx_offset +// [Method ] = method() method_offset + +// [last esp ] = last_sp() last_sp_offset +// [old stack pointer ] (sender_sp) sender_sp_offset + +// [old frame pointer ] +// [return pc ] + +// [last sp ] <- fp = link() +// [oop temp ] (only for native calls) + +// [padding ] (to preserve machine SP alignment) +// [locals and parameters ] +// <- sender sp +// ------------------------------ Asm interpreter ---------------------------------------- + +// ------------------------------ C Frame ------------------------------------------------ +// Stack: gcc with -fno-omit-frame-pointer +// . +// . +// +-> . +// | +-----------------+ | +// | | return address | | +// | | previous fp ------+ +// | | saved registers | +// | | local variables | +// | | ... | <-+ +// | +-----------------+ | +// | | return address | | +// +------ previous fp | | +// | saved registers | | +// | local variables | | +// +-> | ... | | +// | +-----------------+ | +// | | return address | | +// | | previous fp ------+ +// | | saved registers | +// | | local variables | +// | | ... | <-+ +// | +-----------------+ | +// | | return address | | +// +------ previous fp | | +// | saved registers | | +// | local variables | | +// $fp --> | ... | | +// +-----------------+ | +// | return address | | +// | previous fp ------+ +// | saved registers | +// $sp --> | local variables | +// +-----------------+ +// ------------------------------ C Frame ------------------------------------------------ + + public: + enum { + pc_return_offset = 0, + // All frames + link_offset = -2, + return_addr_offset = -1, + sender_sp_offset = 0, + // Interpreter frames + interpreter_frame_oop_temp_offset = 1, // for native calls only + + interpreter_frame_sender_sp_offset = -3, + // outgoing sp before a call to an invoked method + interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1, + interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1, + interpreter_frame_mdp_offset = interpreter_frame_method_offset - 1, + interpreter_frame_padding_offset = interpreter_frame_mdp_offset - 1, + interpreter_frame_mirror_offset = interpreter_frame_padding_offset - 1, + interpreter_frame_cache_offset = interpreter_frame_mirror_offset - 1, + interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1, + interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1, + interpreter_frame_initial_sp_offset = interpreter_frame_bcp_offset - 1, + + interpreter_frame_monitor_block_top_offset = interpreter_frame_initial_sp_offset, + interpreter_frame_monitor_block_bottom_offset = interpreter_frame_initial_sp_offset, + + // Entry frames + // n.b. these values are determined by the layout defined in + // stubGenerator for the Java call stub + entry_frame_after_call_words = 22, + entry_frame_call_wrapper_offset = -10, + + // we don't need a save area + arg_reg_save_area_bytes = 0 + }; + + intptr_t ptr_at(int offset) const { + return *ptr_at_addr(offset); + } + + void ptr_at_put(int offset, intptr_t value) { + *ptr_at_addr(offset) = value; + } + + private: + // an additional field beyond _sp and _pc: + intptr_t* _fp; // frame pointer + // The interpreter and adapters will extend the frame of the caller. + // Since oopMaps are based on the sp of the caller before extension + // we need to know that value. However in order to compute the address + // of the return address we need the real "raw" sp. Since sparc already + // uses sp() to mean "raw" sp and unextended_sp() to mean the caller's + // original sp we use that convention. + + intptr_t* _unextended_sp; + void adjust_unextended_sp(); + + intptr_t* ptr_at_addr(int offset) const { + return (intptr_t*) addr_at(offset); + } + +#ifdef ASSERT + // Used in frame::sender_for_{interpreter,compiled}_frame + static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp); +#endif + + public: + // Constructors + + frame(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc); + + frame(intptr_t* ptr_sp, intptr_t* unextended_sp, intptr_t* ptr_fp, address pc); + + frame(intptr_t* ptr_sp, intptr_t* ptr_fp); + + void init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc); + + // accessors for the instance variables + // Note: not necessarily the real 'frame pointer' (see real_fp) + intptr_t* fp() const { return _fp; } + + inline address* sender_pc_addr() const; + + // expression stack tos if we are nested in a java call + intptr_t* interpreter_frame_last_sp() const; + + // helper to update a map with callee-saved RBP + static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr); + + // deoptimization support + void interpreter_frame_set_last_sp(intptr_t* last_sp); + + static jint interpreter_frame_expression_stack_direction() { return -1; } + + // returns the sending frame, without applying any barriers + frame sender_raw(RegisterMap* map) const; + +#endif // CPU_RISCV_FRAME_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5ac1bf57f57dbd3359315e92388af27a43c98cb6 --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_FRAME_RISCV_INLINE_HPP +#define CPU_RISCV_FRAME_RISCV_INLINE_HPP + +#include "code/codeCache.hpp" +#include "code/vmreg.inline.hpp" + +// Inline functions for RISCV frames: + +// Constructors: + +inline frame::frame() { + _pc = NULL; + _sp = NULL; + _unextended_sp = NULL; + _fp = NULL; + _cb = NULL; + _deopt_state = unknown; +} + +static int spin; + +inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) { + intptr_t a = intptr_t(ptr_sp); + intptr_t b = intptr_t(ptr_fp); + _sp = ptr_sp; + _unextended_sp = ptr_sp; + _fp = ptr_fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = CodeCache::find_blob(pc); + adjust_unextended_sp(); + + address original_pc = CompiledMethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } +} + +inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) { + init(ptr_sp, ptr_fp, pc); +} + +inline frame::frame(intptr_t* ptr_sp, intptr_t* unextended_sp, intptr_t* ptr_fp, address pc) { + intptr_t a = intptr_t(ptr_sp); + intptr_t b = intptr_t(ptr_fp); + _sp = ptr_sp; + _unextended_sp = unextended_sp; + _fp = ptr_fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = CodeCache::find_blob(pc); + adjust_unextended_sp(); + + address original_pc = CompiledMethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc), + "original PC must be in the main code section of the the compiled method (or must be immediately following it)"); + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } +} + +inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) { + intptr_t a = intptr_t(ptr_sp); + intptr_t b = intptr_t(ptr_fp); + _sp = ptr_sp; + _unextended_sp = ptr_sp; + _fp = ptr_fp; + _pc = (address)(ptr_sp[-1]); + + // Here's a sticky one. This constructor can be called via AsyncGetCallTrace + // when last_Java_sp is non-null but the pc fetched is junk. If we are truly + // unlucky the junk value could be to a zombied method and we'll die on the + // find_blob call. This is also why we can have no asserts on the validity + // of the pc we find here. AsyncGetCallTrace -> pd_get_top_frame_for_signal_handler + // -> pd_last_frame should use a specialized version of pd_last_frame which could + // call a specilaized frame constructor instead of this one. + // Then we could use the assert below. However this assert is of somewhat dubious + // value. + + _cb = CodeCache::find_blob(_pc); + adjust_unextended_sp(); + + address original_pc = CompiledMethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } +} + +// Accessors + +inline bool frame::equal(frame other) const { + bool ret = sp() == other.sp() && + unextended_sp() == other.unextended_sp() && + fp() == other.fp() && + pc() == other.pc(); + assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction"); + return ret; +} + +// Return unique id for this frame. The id must have a value where we can distinguish +// identity and younger/older relationship. NULL represents an invalid (incomparable) +// frame. +inline intptr_t* frame::id(void) const { return unextended_sp(); } + +// Return true if the frame is older (less recent activation) than the frame represented by id +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 +inline address* frame::sender_pc_addr() const { return (address*) addr_at(return_addr_offset); } +inline address frame::sender_pc() const { return *sender_pc_addr(); } +inline intptr_t* frame::sender_sp() const { return addr_at(sender_sp_offset); } + +inline intptr_t** frame::interpreter_frame_locals_addr() const { + return (intptr_t**)addr_at(interpreter_frame_locals_offset); +} + +inline intptr_t* frame::interpreter_frame_last_sp() const { + return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset); +} + +inline intptr_t* frame::interpreter_frame_bcp_addr() const { + return (intptr_t*)addr_at(interpreter_frame_bcp_offset); +} + +inline intptr_t* frame::interpreter_frame_mdp_addr() const { + return (intptr_t*)addr_at(interpreter_frame_mdp_offset); +} + + +// Constant pool cache + +inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const { + return (ConstantPoolCache**)addr_at(interpreter_frame_cache_offset); +} + +// Method + +inline Method** frame::interpreter_frame_method_addr() const { + return (Method**)addr_at(interpreter_frame_method_offset); +} + +// Mirror + +inline oop* frame::interpreter_frame_mirror_addr() const { + return (oop*)addr_at(interpreter_frame_mirror_offset); +} + +// top of expression stack +inline intptr_t* frame::interpreter_frame_tos_address() const { + intptr_t* last_sp = interpreter_frame_last_sp(); + if (last_sp == NULL) { + return sp(); + } else { + // sp() may have been extended or shrunk by an adapter. At least + // check that we don't fall behind the legal region. + // For top deoptimized frame last_sp == interpreter_frame_monitor_end. + assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos"); + return last_sp; + } +} + +inline oop* frame::interpreter_frame_temp_oop_addr() const { + return (oop *)(fp() + interpreter_frame_oop_temp_offset); +} + +inline int frame::interpreter_frame_monitor_size() { + return BasicObjectLock::size(); +} + + +// expression stack +// (the max_stack arguments are used by the GC; see class FrameClosure) + +inline intptr_t* frame::interpreter_frame_expression_stack() const { + intptr_t* monitor_end = (intptr_t*) interpreter_frame_monitor_end(); + return monitor_end-1; +} + + +// Entry frames + +inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const { + return (JavaCallWrapper**)addr_at(entry_frame_call_wrapper_offset); +} + + +// Compiled frames +PRAGMA_DIAG_PUSH +PRAGMA_NONNULL_IGNORED +inline oop frame::saved_oop_result(RegisterMap* map) const { + oop* result_adr = (oop *)map->location(x10->as_VMReg()); + guarantee(result_adr != NULL, "bad register save location"); + return (*result_adr); +} + +inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { + oop* result_adr = (oop *)map->location(x10->as_VMReg()); + guarantee(result_adr != NULL, "bad register save location"); + *result_adr = obj; +} +PRAGMA_DIAG_POP + +#endif // CPU_RISCV_FRAME_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c46b3947d3c88310adaae1f50314c2aa962768f --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "gc/g1/g1BarrierSet.hpp" +#include "gc/g1/g1BarrierSetAssembler.hpp" +#include "gc/g1/g1BarrierSetRuntime.hpp" +#include "gc/g1/g1CardTable.hpp" +#include "gc/g1/g1ThreadLocalData.hpp" +#include "gc/g1/heapRegion.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interp_masm.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.hpp" +#ifdef COMPILER1 +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "gc/g1/c1/g1BarrierSetC1.hpp" +#endif + +#define __ masm-> + +void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register addr, Register count, RegSet saved_regs) { + assert_cond(masm != NULL); + bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + if (!dest_uninitialized) { + Label done; + Address in_progress(xthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); + + // Is marking active? + if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { + __ lwu(t0, in_progress); + } else { + assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbu(t0, in_progress); + } + __ beqz(t0, done); + + __ push_reg(saved_regs, sp); + if (count == c_rarg0) { + if (addr == c_rarg1) { + // exactly backwards!! + __ mv(t0, c_rarg0); + __ mv(c_rarg0, c_rarg1); + __ mv(c_rarg1, t0); + } else { + __ mv(c_rarg1, count); + __ mv(c_rarg0, addr); + } + } else { + __ mv(c_rarg0, addr); + __ mv(c_rarg1, count); + } + if (UseCompressedOops) { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_narrow_oop_entry), 2); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 2); + } + __ pop_reg(saved_regs, sp); + + __ bind(done); + } +} + +void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs) { + assert_cond(masm != NULL); + __ push_reg(saved_regs, sp); + assert_different_registers(start, count, tmp); + assert_different_registers(c_rarg0, count); + __ mv(c_rarg0, start); + __ mv(c_rarg1, count); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2); + __ pop_reg(saved_regs, sp); +} + +void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + // If expand_call is true then we expand the call_VM_leaf macro + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + + assert_cond(masm != NULL); + assert(thread == xthread, "must be"); + + Label done; + Label runtime; + + assert_different_registers(obj, pre_val, tmp, t0); + assert(pre_val != noreg && tmp != noreg, "expecting a register"); + + Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); + Address index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); + + // Is marking active? + if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { // 4-byte width + __ lwu(tmp, in_progress); + } else { + assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbu(tmp, in_progress); + } + __ beqz(tmp, done); + + // Do we need to load the previous value? + if (obj != noreg) { + __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); + } + + // Is the previous value null? + __ beqz(pre_val, done); + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + + __ ld(tmp, index); // tmp := *index_adr + __ beqz(tmp, runtime); // tmp == 0? + // If yes, goto runtime + + __ sub(tmp, tmp, wordSize); // tmp := tmp - wordSize + __ sd(tmp, index); // *index_adr := tmp + __ ld(t0, buffer); + __ add(tmp, tmp, t0); // tmp := tmp + *buffer_adr + + // Record the previous value + __ sd(pre_val, Address(tmp, 0)); + __ j(done); + + __ bind(runtime); + // save the live input values + RegSet saved = RegSet::of(pre_val); + if (tosca_live) { saved += RegSet::of(x10); } + if (obj != noreg) { saved += RegSet::of(obj); } + + __ push_reg(saved, sp); + + if (expand_call) { + assert(pre_val != c_rarg1, "smashed arg"); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); + } + + __ pop_reg(saved, sp); + + __ bind(done); + +} + +void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, + Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2) { + assert_cond(masm != NULL); + assert(thread == xthread, "must be"); + assert_different_registers(store_addr, new_val, thread, tmp, tmp2, + t0); + assert(store_addr != noreg && new_val != noreg && tmp != noreg && + tmp2 != noreg, "expecting a register"); + + Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); + Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); + + BarrierSet* bs = BarrierSet::barrier_set(); + CardTableBarrierSet* ctbs = barrier_set_cast(bs); + CardTable* ct = ctbs->card_table(); + + Label done; + Label runtime; + + // Does store cross heap regions? + + __ xorr(tmp, store_addr, new_val); + __ srli(tmp, tmp, HeapRegion::LogOfHRGrainBytes); + __ beqz(tmp, done); + + // crosses regions, storing NULL? + + __ beqz(new_val, done); + + // storing region crossing non-NULL, is card already dirty? + + ExternalAddress cardtable((address) ct->byte_map_base()); + const Register card_addr = tmp; + + __ srli(card_addr, store_addr, CardTable::card_shift()); + + // get the address of the card + __ load_byte_map_base(tmp2); + __ add(card_addr, card_addr, tmp2); + __ lbu(tmp2, Address(card_addr)); + __ mv(t0, (int)G1CardTable::g1_young_card_val()); + __ beq(tmp2, t0, done); + + assert((int)CardTable::dirty_card_val() == 0, "must be 0"); + + __ membar(MacroAssembler::StoreLoad); + + __ lbu(tmp2, Address(card_addr)); + __ beqz(tmp2, done); + + // storing a region crossing, non-NULL oop, card is clean. + // dirty card and log. + + __ sb(zr, Address(card_addr)); + + __ ld(t0, queue_index); + __ beqz(t0, runtime); + __ sub(t0, t0, wordSize); + __ sd(t0, queue_index); + + __ ld(tmp2, buffer); + __ add(t0, tmp2, t0); + __ sd(card_addr, Address(t0, 0)); + __ j(done); + + __ bind(runtime); + // save the live input values + RegSet saved = RegSet::of(store_addr); + __ push_reg(saved, sp); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); + __ pop_reg(saved, sp); + + __ bind(done); +} + +void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { + assert_cond(masm != NULL); + bool on_oop = is_reference_type(type); + bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; + bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; + bool on_reference = on_weak || on_phantom; + ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + if (on_oop && on_reference) { + // RA is live. It must be saved around calls. + __ enter(); // 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 */, + noreg /* obj */, + dst /* pre_val */, + xthread /* thread */, + tmp1 /* tmp */, + true /* tosca_live */, + true /* expand_call */); + __ leave(); + } +} + +void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + assert_cond(masm != NULL); + // flatten object address if needed + if (dst.offset() == 0) { + if (dst.base() != x13) { + __ mv(x13, dst.base()); + } + } else { + __ la(x13, dst); + } + + g1_write_barrier_pre(masm, + x13 /* obj */, + tmp2 /* pre_val */, + xthread /* thread */, + tmp1 /* tmp */, + val != noreg /* tosca_live */, + false /* expand_call */); + + if (val == noreg) { + BarrierSetAssembler::store_at(masm, decorators, type, Address(x13, 0), noreg, noreg, noreg); + } else { + // G1 barrier needs uncompressed oop for region cross check. + Register new_val = val; + if (UseCompressedOops) { + new_val = t1; + __ mv(new_val, val); + } + BarrierSetAssembler::store_at(masm, decorators, type, Address(x13, 0), val, noreg, noreg); + g1_write_barrier_post(masm, + x13 /* store_adr */, + new_val /* new_val */, + xthread /* thread */, + tmp1 /* tmp */, + tmp2 /* tmp2 */); + } +} + +#ifdef COMPILER1 + +#undef __ +#define __ ce->masm()-> + +void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) { + G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); + + // At this point we know that marking is in progress. + // If do_load() is true then we have to emit the + // load of the previous value; otherwise it has already + // been loaded into _pre_val. + __ bind(*stub->entry()); + + assert(stub->pre_val()->is_register(), "Precondition."); + + Register pre_val_reg = stub->pre_val()->as_register(); + + if (stub->do_load()) { + ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); + } + __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); + ce->store_parameter(stub->pre_val()->as_register(), 0); + __ far_call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin())); + __ j(*stub->continuation()); +} + +void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) { + G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); + __ bind(*stub->entry()); + assert(stub->addr()->is_register(), "Precondition"); + assert(stub->new_val()->is_register(), "Precondition"); + Register new_val_reg = stub->new_val()->as_register(); + __ beqz(new_val_reg, *stub->continuation(), /* is_far */ true); + ce->store_parameter(stub->addr()->as_pointer_register(), 0); + __ far_call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin())); + __ j(*stub->continuation()); +} + +#undef __ + +#define __ sasm-> + +void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) { + __ prologue("g1_pre_barrier", false); + + BarrierSet* bs = BarrierSet::barrier_set(); + + // arg0 : previous value of memory + const Register pre_val = x10; + const Register thread = xthread; + const Register tmp = t0; + + Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); + Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); + + Label done; + Label runtime; + + // Is marking still active? + if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { // 4-byte width + __ lwu(tmp, in_progress); + } else { + assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbu(tmp, in_progress); + } + __ beqz(tmp, done); + + // Can we store original value in the thread's buffer? + __ ld(tmp, queue_index); + __ beqz(tmp, runtime); + + __ sub(tmp, tmp, wordSize); + __ sd(tmp, queue_index); + __ ld(t1, buffer); + __ add(tmp, tmp, t1); + __ load_parameter(0, t1); + __ sd(t1, Address(tmp, 0)); + __ j(done); + + __ bind(runtime); + __ push_call_clobbered_registers(); + __ load_parameter(0, pre_val); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); + __ pop_call_clobbered_registers(); + __ bind(done); + + __ epilogue(); +} + +void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) { + __ prologue("g1_post_barrier", false); + + // arg0 : store_address + Address store_addr(fp, 2 * BytesPerWord); // 2 BytesPerWord from fp + + BarrierSet* bs = BarrierSet::barrier_set(); + CardTableBarrierSet* ctbs = barrier_set_cast(bs); + CardTable* ct = ctbs->card_table(); + + Label done; + Label runtime; + + // At this point we know new_value is non-NULL and the new_value crosses regions. + // Must check to see if card is already dirty + const Register thread = xthread; + + Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); + Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); + + const Register card_offset = t1; + // RA is free here, so we can use it to hold the byte_map_base. + const Register byte_map_base = ra; + + assert_different_registers(card_offset, byte_map_base, t0); + + __ load_parameter(0, card_offset); + __ srli(card_offset, card_offset, CardTable::card_shift()); + __ load_byte_map_base(byte_map_base); + + // Convert card offset into an address in card_addr + Register card_addr = card_offset; + __ add(card_addr, byte_map_base, card_addr); + + __ lbu(t0, Address(card_addr, 0)); + __ sub(t0, t0, (int)G1CardTable::g1_young_card_val()); + __ beqz(t0, done); + + assert((int)CardTable::dirty_card_val() == 0, "must be 0"); + + __ membar(MacroAssembler::StoreLoad); + __ lbu(t0, Address(card_addr, 0)); + __ beqz(t0, done); + + // storing region crossing non-NULL, card is clean. + // dirty card and log. + __ sb(zr, Address(card_addr, 0)); + + __ ld(t0, queue_index); + __ beqz(t0, runtime); + __ sub(t0, t0, wordSize); + __ sd(t0, queue_index); + + // Reuse RA to hold buffer_addr + const Register buffer_addr = ra; + + __ ld(buffer_addr, buffer); + __ add(t0, buffer_addr, t0); + __ sd(card_addr, Address(t0, 0)); + __ j(done); + + __ bind(runtime); + __ push_call_clobbered_registers(); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); + __ pop_call_clobbered_registers(); + __ bind(done); + __ epilogue(); +} + +#undef __ + +#endif // COMPILER1 diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..37bc183f39c76873b06ceb512ccf648935569b72 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_G1_G1BARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_G1_G1BARRIERSETASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/modRefBarrierSetAssembler.hpp" +#include "utilities/macros.hpp" + +#ifdef COMPILER1 +class LIR_Assembler; +#endif +class StubAssembler; +class G1PreBarrierStub; +class G1PostBarrierStub; + +class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { +protected: + void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register addr, Register count, RegSet saved_regs); + void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs); + + void g1_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + + void g1_write_barrier_post(MacroAssembler* masm, + Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2); + + virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); + +public: +#ifdef COMPILER1 + void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub); + void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub); + + void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); + void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm); +#endif + + void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread); +}; + +#endif // CPU_RISCV_GC_G1_G1BARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp b/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8735fd014ffff76b820519b55bf3b7bd4a0133d8 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_G1_G1GLOBALS_RISCV_HPP +#define CPU_RISCV_GC_G1_G1GLOBALS_RISCV_HPP + +const size_t G1MergeHeapRootsPrefetchCacheSize = 16; + +#endif // CPU_RISCV_GC_G1_G1GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c115a2ea02a5e077e9e74e53715817e815dad0d --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "classfile/classLoaderData.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/barrierSetNMethod.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interp_masm.hpp" +#include "memory/universe.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.hpp" + +#define __ masm-> + +void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { + assert_cond(masm != NULL); + + // RA is live. It must be saved around calls. + + bool in_heap = (decorators & IN_HEAP) != 0; + bool in_native = (decorators & IN_NATIVE) != 0; + bool is_not_null = (decorators & IS_NOT_NULL) != 0; + switch (type) { + case T_OBJECT: // fall through + case T_ARRAY: { + if (in_heap) { + if (UseCompressedOops) { + __ lwu(dst, src); + if (is_not_null) { + __ decode_heap_oop_not_null(dst); + } else { + __ decode_heap_oop(dst); + } + } else { + __ ld(dst, src); + } + } else { + assert(in_native, "why else?"); + __ ld(dst, src); + } + break; + } + case T_BOOLEAN: __ load_unsigned_byte (dst, src); break; + case T_BYTE: __ load_signed_byte (dst, src); break; + case T_CHAR: __ load_unsigned_short(dst, src); break; + case T_SHORT: __ load_signed_short (dst, src); break; + case T_INT: __ lw (dst, src); break; + case T_LONG: __ ld (dst, src); break; + case T_ADDRESS: __ ld (dst, src); break; + case T_FLOAT: __ flw (f10, src); break; + case T_DOUBLE: __ fld (f10, src); break; + default: Unimplemented(); + } +} + +void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + assert_cond(masm != NULL); + bool in_heap = (decorators & IN_HEAP) != 0; + bool in_native = (decorators & IN_NATIVE) != 0; + switch (type) { + case T_OBJECT: // fall through + case T_ARRAY: { + val = val == noreg ? zr : val; + if (in_heap) { + if (UseCompressedOops) { + assert(!dst.uses(val), "not enough registers"); + if (val != zr) { + __ encode_heap_oop(val); + } + __ sw(val, dst); + } else { + __ sd(val, dst); + } + } else { + assert(in_native, "why else?"); + __ sd(val, dst); + } + break; + } + case T_BOOLEAN: + __ andi(val, val, 0x1); // boolean is true if LSB is 1 + __ sb(val, dst); + break; + case T_BYTE: __ sb(val, dst); break; + case T_CHAR: __ sh(val, dst); break; + case T_SHORT: __ sh(val, dst); break; + case T_INT: __ sw(val, dst); break; + case T_LONG: __ sd(val, dst); break; + case T_ADDRESS: __ sd(val, dst); break; + case T_FLOAT: __ fsw(f10, dst); break; + case T_DOUBLE: __ fsd(f10, dst); break; + default: Unimplemented(); + } + +} + +void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath) { + assert_cond(masm != NULL); + // If mask changes we need to ensure that the inverse is still encodable as an immediate + STATIC_ASSERT(JNIHandles::weak_tag_mask == 1); + __ andi(obj, obj, ~JNIHandles::weak_tag_mask); + __ ld(obj, Address(obj, 0)); // *obj +} + +// Defines obj, preserves var_size_in_bytes, okay for tmp2 == var_size_in_bytes. +void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp1, + Register tmp2, + Label& slow_case, + bool is_far) { + assert_cond(masm != NULL); + assert_different_registers(obj, tmp2); + assert_different_registers(obj, var_size_in_bytes); + Register end = tmp2; + + __ ld(obj, Address(xthread, JavaThread::tlab_top_offset())); + if (var_size_in_bytes == noreg) { + __ la(end, Address(obj, con_size_in_bytes)); + } else { + __ add(end, obj, var_size_in_bytes); + } + __ ld(t0, Address(xthread, JavaThread::tlab_end_offset())); + __ bgtu(end, t0, slow_case, is_far); + + // update the tlab top pointer + __ sd(end, Address(xthread, JavaThread::tlab_top_offset())); + + // recover var_size_in_bytes if necessary + if (var_size_in_bytes == end) { + __ sub(var_size_in_bytes, var_size_in_bytes, obj); + } +} + +// Defines obj, preserves var_size_in_bytes +void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp1, + Label& slow_case, + bool is_far) { + assert_cond(masm != NULL); + assert_different_registers(obj, var_size_in_bytes, tmp1); + if (!Universe::heap()->supports_inline_contig_alloc()) { + __ j(slow_case); + } else { + Register end = tmp1; + Label retry; + __ bind(retry); + + // Get the current end of the heap + ExternalAddress address_end((address) Universe::heap()->end_addr()); + { + int32_t offset; + __ la_patchable(t1, address_end, offset); + __ ld(t1, Address(t1, offset)); + } + + // Get the current top of the heap + ExternalAddress address_top((address) Universe::heap()->top_addr()); + { + int32_t offset; + __ la_patchable(t0, address_top, offset); + __ addi(t0, t0, offset); + __ lr_d(obj, t0, Assembler::aqrl); + } + + // Adjust it my the size of our new object + if (var_size_in_bytes == noreg) { + __ la(end, Address(obj, con_size_in_bytes)); + } else { + __ add(end, obj, var_size_in_bytes); + } + + // if end < obj then we wrapped around high memory + __ bltu(end, obj, slow_case, is_far); + + __ bgtu(end, t1, slow_case, is_far); + + // If heap_top hasn't been changed by some other thread, update it. + __ sc_d(t1, end, t0, Assembler::rl); + __ bnez(t1, retry); + + incr_allocated_bytes(masm, var_size_in_bytes, con_size_in_bytes, tmp1); + } +} + +void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp1) { + assert_cond(masm != NULL); + assert(tmp1->is_valid(), "need temp reg"); + + __ ld(tmp1, Address(xthread, in_bytes(JavaThread::allocated_bytes_offset()))); + if (var_size_in_bytes->is_valid()) { + __ add(tmp1, tmp1, var_size_in_bytes); + } else { + __ add(tmp1, tmp1, con_size_in_bytes); + } + __ sd(tmp1, Address(xthread, in_bytes(JavaThread::allocated_bytes_offset()))); +} + +void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + + if (bs_nm == NULL) { + return; + } + + // RISCV atomic operations require that the memory address be naturally aligned. + __ align(4); + + Label skip, guard; + Address thread_disarmed_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset())); + + __ lwu(t0, guard); + + // Subsequent loads of oops must occur after load of guard value. + // BarrierSetNMethod::disarm sets guard with release semantics. + __ membar(MacroAssembler::LoadLoad); + __ lwu(t1, thread_disarmed_addr); + __ beq(t0, t1, skip); + + int32_t offset = 0; + __ movptr_with_offset(t0, StubRoutines::riscv::method_entry_barrier(), offset); + __ jalr(ra, t0, offset); + __ j(skip); + + __ bind(guard); + + assert(__ offset() % 4 == 0, "bad alignment"); + __ emit_int32(0); // nmethod guard value. Skipped over in common case. + + __ bind(skip); +} + +void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { + BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs == NULL) { + return; + } + + Label bad_call; + __ beqz(xmethod, bad_call); + + // Pointer chase to the method holder to find out if the method is concurrently unloading. + Label method_live; + __ load_method_holder_cld(t0, xmethod); + + // Is it a strong CLD? + __ lwu(t1, Address(t0, ClassLoaderData::keep_alive_offset())); + __ bnez(t1, method_live); + + // Is it a weak but alive CLD? + __ push_reg(RegSet::of(x28, x29), sp); + + __ ld(x28, Address(t0, ClassLoaderData::holder_offset())); + + // Uses x28 & x29, so we must pass new temporaries. + __ resolve_weak_handle(x28, x29); + __ mv(t0, x28); + + __ pop_reg(RegSet::of(x28, x29), sp); + + __ bnez(t0, method_live); + + __ bind(bad_call); + + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + __ bind(method_live); +} diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b85f7f5582b2a8a4a0ee82f0e427d720b1cefd72 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_SHARED_BARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_SHARED_BARRIERSETASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" +#include "memory/allocation.hpp" +#include "oops/access.hpp" + +class BarrierSetAssembler: public CHeapObj { +private: + void incr_allocated_bytes(MacroAssembler* masm, + Register var_size_in_bytes, int con_size_in_bytes, + Register t1 = noreg); + +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) {} + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register start, Register end, Register tmp, RegSet saved_regs) {} + 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); + + virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath); + + virtual void tlab_allocate(MacroAssembler* masm, + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + Label& slow_case, // continuation point if fast allocation fails + bool is_far = false + ); + + void eden_allocate(MacroAssembler* masm, + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Label& slow_case, // continuation point if fast allocation fails + bool is_far = false + ); + virtual void barrier_stubs_init() {} + + virtual void nmethod_entry_barrier(MacroAssembler* masm); + virtual void c2i_entry_barrier(MacroAssembler* masm); + virtual ~BarrierSetAssembler() {} +}; + +#endif // CPU_RISCV_GC_SHARED_BARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae7ee4c5a44a04da679b16583b7a7a2fb4b8e9fd --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "code/codeCache.hpp" +#include "code/nativeInst.hpp" +#include "gc/shared/barrierSetNMethod.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/registerMap.hpp" +#include "runtime/thread.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" + +class NativeNMethodBarrier: public NativeInstruction { + address instruction_address() const { return addr_at(0); } + + int *guard_addr() { + /* auipc + lwu + fence + lwu + beq + lui + addi + slli + addi + slli + jalr + j */ + return reinterpret_cast(instruction_address() + 12 * 4); + } + +public: + int get_value() { + return Atomic::load_acquire(guard_addr()); + } + + void set_value(int value) { + Atomic::release_store(guard_addr(), value); + } + + void verify() const; +}; + +// Store the instruction bitmask, bits and name for checking the barrier. +struct CheckInsn { + uint32_t mask; + uint32_t bits; + const char *name; +}; + +static const struct CheckInsn barrierInsn[] = { + { 0x00000fff, 0x00000297, "auipc t0, 0 "}, + { 0x000fffff, 0x0002e283, "lwu t0, 48(t0) "}, + { 0xffffffff, 0x0aa0000f, "fence ir, ir "}, + { 0x000fffff, 0x000be303, "lwu t1, 112(xthread)"}, + { 0x01fff07f, 0x00628063, "beq t0, t1, skip "}, + { 0x00000fff, 0x000002b7, "lui t0, imm0 "}, + { 0x000fffff, 0x00028293, "addi t0, t0, imm1 "}, + { 0xffffffff, 0x00b29293, "slli t0, t0, 11 "}, + { 0x000fffff, 0x00028293, "addi t0, t0, imm2 "}, + { 0xffffffff, 0x00529293, "slli t0, t0, 5 "}, + { 0x000fffff, 0x000280e7, "jalr ra, imm3(t0) "}, + { 0x00000fff, 0x0000006f, "j skip "} + /* guard: */ + /* 32bit nmethod guard value */ + /* skip: */ +}; + +// The encodings must match the instructions emitted by +// BarrierSetAssembler::nmethod_entry_barrier. The matching ignores the specific +// register numbers and immediate values in the encoding. +void NativeNMethodBarrier::verify() const { + intptr_t addr = (intptr_t) instruction_address(); + for(unsigned int i = 0; i < sizeof(barrierInsn)/sizeof(struct CheckInsn); i++ ) { + uint32_t inst = *((uint32_t*) addr); + if ((inst & barrierInsn[i].mask) != barrierInsn[i].bits) { + tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", addr, inst); + fatal("not an %s instruction.", barrierInsn[i].name); + } + addr += 4; + } +} + + +/* We're called from an nmethod when we need to deoptimize it. We do + this by throwing away the nmethod's frame and jumping to the + ic_miss stub. This looks like there has been an IC miss at the + entry of the nmethod, so we resolve the call, which will fall back + to the interpreter if the nmethod has been unloaded. */ +void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { + + typedef struct { + intptr_t *sp; intptr_t *fp; address ra; address pc; + } frame_pointers_t; + + frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5); + + JavaThread *thread = JavaThread::current(); + RegisterMap reg_map(thread, false); + frame frame = thread->last_frame(); + + assert(frame.is_compiled_frame() || frame.is_native_frame(), "must be"); + assert(frame.cb() == nm, "must be"); + frame = frame.sender(®_map); + + LogTarget(Trace, nmethod, barrier) out; + if (out.is_enabled()) { + ResourceMark mark; + log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", + nm->method()->name_and_sig_as_C_string(), + nm, *(address *) return_address_ptr, nm->is_osr_method(), thread, + thread->name(), frame.sp(), nm->verified_entry_point()); + } + + new_frame->sp = frame.sp(); + new_frame->fp = frame.fp(); + new_frame->ra = frame.pc(); + new_frame->pc = SharedRuntime::get_handle_wrong_method_stub(); +} + +// This is the offset of the entry barrier from where the frame is completed. +// If any code changes between the end of the verified entry where the entry +// barrier resides, and the completion of the frame, then +// NativeNMethodCmpBarrier::verify() will immediately complain when it does +// not find the expected native instruction at this offset, which needs updating. +// Note that this offset is invariant of PreserveFramePointer. + +// see BarrierSetAssembler::nmethod_entry_barrier +// auipc + lwu + fence + lwu + beq + movptr_with_offset(5 instructions) + jalr + j + int32 +static const int entry_barrier_offset = -4 * 13; + +static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { + address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset; + NativeNMethodBarrier* barrier = reinterpret_cast(barrier_address); + debug_only(barrier->verify()); + return barrier; +} + +void BarrierSetNMethod::disarm(nmethod* nm) { + if (!supports_entry_barrier(nm)) { + return; + } + + // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. + NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); + + barrier->set_value(disarmed_value()); +} + +bool BarrierSetNMethod::is_armed(nmethod* nm) { + if (!supports_entry_barrier(nm)) { + return false; + } + + NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); + return barrier->get_value() != disarmed_value(); +} diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a419f92b5f6fc75a74f305dfb189475a6e14ac65 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/cardTableBarrierSetAssembler.hpp" +#include "gc/shared/gc_globals.hpp" +#include "interpreter/interp_masm.hpp" + +#define __ masm-> + + +void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Register tmp) { + assert_cond(masm != NULL); + assert_different_registers(obj, tmp); + BarrierSet* bs = BarrierSet::barrier_set(); + assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); + + __ srli(obj, obj, CardTable::card_shift()); + + assert(CardTable::dirty_card_val() == 0, "must be"); + + __ load_byte_map_base(tmp); + __ add(tmp, obj, tmp); + + if (UseCondCardMark) { + Label L_already_dirty; + __ membar(MacroAssembler::StoreLoad); + __ lbu(t1, Address(tmp)); + __ beqz(t1, L_already_dirty); + __ sb(zr, Address(tmp)); + __ bind(L_already_dirty); + } else { + __ sb(zr, Address(tmp)); + } +} + +void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs) { + assert_cond(masm != NULL); + assert_different_registers(start, tmp); + assert_different_registers(count, tmp); + + Label L_loop, L_done; + const Register end = count; + + __ beqz(count, L_done); // zero count - nothing to do + // end = start + count << LogBytesPerHeapOop + __ shadd(end, count, start, count, LogBytesPerHeapOop); + __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive + + __ srli(start, start, CardTable::card_shift()); + __ srli(end, end, CardTable::card_shift()); + __ sub(count, end, start); // number of bytes to copy + + __ load_byte_map_base(tmp); + __ add(start, start, tmp); + + __ bind(L_loop); + __ add(tmp, start, count); + __ sb(zr, Address(tmp)); + __ sub(count, count, 1); + __ bgez(count, L_loop); + __ bind(L_done); +} + +void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + bool in_heap = (decorators & IN_HEAP) != 0; + bool is_array = (decorators & IS_ARRAY) != 0; + bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; + bool precise = is_array || on_anonymous; + + bool needs_post_barrier = val != noreg && in_heap; + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, noreg, noreg); + if (needs_post_barrier) { + // flatten object address if needed + if (!precise || dst.offset() == 0) { + store_check(masm, dst.base(), x13); + } else { + assert_cond(masm != NULL); + __ la(x13, dst); + store_check(masm, x13, t0); + } + } +} diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..686fe8fa4786186f4d760b6193235ccdc56a2beb --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/modRefBarrierSetAssembler.hpp" + +class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler { +protected: + void store_check(MacroAssembler* masm, Register obj, Register tmp); + + virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs); + virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); +}; + +#endif // #ifndef CPU_RISCV_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7aa2015f9ec0ec5bae86425eb43a828833c846d5 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "gc/shared/modRefBarrierSetAssembler.hpp" + +#define __ masm-> + +void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) { + + if (is_oop) { + gen_write_ref_array_pre_barrier(masm, decorators, dst, count, saved_regs); + } +} + +void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register start, Register count, Register tmp, + RegSet saved_regs) { + if (is_oop) { + gen_write_ref_array_post_barrier(masm, decorators, start, count, tmp, saved_regs); + } +} + +void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + if (is_reference_type(type)) { + oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2); + } else { + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + } +} diff --git a/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..00419c3163c2da38ac65af6f32ecaf72d19ad572 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_SHARED_MODREFBARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_SHARED_MODREFBARRIERSETASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSetAssembler.hpp" + +// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other +// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected +// accesses, which are overridden in the concrete BarrierSetAssembler. + +class ModRefBarrierSetAssembler: public BarrierSetAssembler { +protected: + virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register addr, Register count, RegSet saved_regs) {} + virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs) {} + + virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) = 0; + +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs); + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register start, Register count, Register tmp, RegSet saved_regs); + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); +}; + +#endif // CPU_RISCV_GC_SHARED_MODREFBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd568cc723fe9d05a97a35de84c3df73b0bb1baf --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "gc/shared/gc_globals.hpp" +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" + +#define __ masm->masm()-> + +void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) { + Register addr = _addr->as_register_lo(); + Register newval = _new_value->as_register(); + Register cmpval = _cmp_value->as_register(); + Register tmp1 = _tmp1->as_register(); + Register tmp2 = _tmp2->as_register(); + Register result = result_opr()->as_register(); + + ShenandoahBarrierSet::assembler()->iu_barrier(masm->masm(), newval, t1); + + if (UseCompressedOops) { + __ encode_heap_oop(tmp1, cmpval); + cmpval = tmp1; + __ encode_heap_oop(tmp2, newval); + newval = tmp2; + } + + ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmpval, newval, /* acquire */ Assembler::aq, + /* release */ Assembler::rl, /* is_cae */ false, result); +} + +#undef __ + +#ifdef ASSERT +#define __ gen->lir(__FILE__, __LINE__)-> +#else +#define __ gen->lir()-> +#endif + +LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) { + BasicType bt = access.type(); + if (access.is_oop()) { + LIRGenerator *gen = access.gen(); + if (ShenandoahSATBBarrier) { + pre_barrier(gen, access.access_emit_info(), access.decorators(), access.resolved_addr(), + LIR_OprFact::illegalOpr /* pre_val */); + } + if (ShenandoahCASBarrier) { + cmp_value.load_item(); + new_value.load_item(); + + LIR_Opr tmp1 = gen->new_register(T_OBJECT); + LIR_Opr tmp2 = gen->new_register(T_OBJECT); + LIR_Opr addr = access.resolved_addr()->as_address_ptr()->base(); + LIR_Opr result = gen->new_register(T_INT); + + __ append(new LIR_OpShenandoahCompareAndSwap(addr, cmp_value.result(), new_value.result(), tmp1, tmp2, result)); + return result; + } + } + return BarrierSetC1::atomic_cmpxchg_at_resolved(access, cmp_value, new_value); +} + +LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value) { + LIRGenerator* gen = access.gen(); + BasicType type = access.type(); + + LIR_Opr result = gen->new_register(type); + value.load_item(); + LIR_Opr value_opr = value.result(); + + if (access.is_oop()) { + value_opr = iu_barrier(access.gen(), value_opr, access.access_emit_info(), access.decorators()); + } + + assert(type == T_INT || is_reference_type(type) LP64_ONLY( || type == T_LONG ), "unexpected type"); + LIR_Opr tmp = gen->new_register(T_INT); + __ xchg(access.resolved_addr(), value_opr, result, tmp); + + if (access.is_oop()) { + result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0), access.decorators()); + LIR_Opr tmp_opr = gen->new_register(type); + __ move(result, tmp_opr); + result = tmp_opr; + if (ShenandoahSATBBarrier) { + pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr, + result /* pre_val */); + } + } + + return result; +} diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0ac6e524364aa7acc8368b68e7ec4903bb40f14 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" +#include "gc/shenandoah/shenandoahForwarding.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahRuntime.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interp_masm.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.hpp" +#ifdef COMPILER1 +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" +#endif + +#define __ masm-> + +void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) { + if (is_oop) { + bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahIUBarrier || ShenandoahLoadRefBarrier) { + + Label done; + + // Avoid calling runtime if count == 0 + __ beqz(count, done); + + // Is GC active? + Address gc_state(xthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + assert_different_registers(src, dst, count, t0); + + __ lbu(t0, gc_state); + if (ShenandoahSATBBarrier && dest_uninitialized) { + __ andi(t0, t0, ShenandoahHeap::HAS_FORWARDED); + __ beqz(t0, done); + } else { + __ andi(t0, t0, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING); + __ beqz(t0, done); + } + + __ push_reg(saved_regs, sp); + if (UseCompressedOops) { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry), + src, dst, count); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry), src, dst, count); + } + __ pop_reg(saved_regs, sp); + __ bind(done); + } + } +} + +void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + if (ShenandoahSATBBarrier) { + satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, tosca_live, expand_call); + } +} + +void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + // If expand_call is true then we expand the call_VM_leaf macro + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + assert(thread == xthread, "must be"); + + Label done; + Label runtime; + + assert_different_registers(obj, pre_val, tmp, t0); + assert(pre_val != noreg && tmp != noreg, "expecting a register"); + + Address in_progress(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset())); + Address index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); + + // Is marking active? + if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { + __ lwu(tmp, in_progress); + } else { + assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbu(tmp, in_progress); + } + __ beqz(tmp, done); + + // Do we need to load the previous value? + if (obj != noreg) { + __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); + } + + // Is the previous value null? + __ beqz(pre_val, done); + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + __ ld(tmp, index); // tmp := *index_adr + __ beqz(tmp, runtime); // tmp == 0? If yes, goto runtime + + __ sub(tmp, tmp, wordSize); // tmp := tmp - wordSize + __ sd(tmp, index); // *index_adr := tmp + __ ld(t0, buffer); + __ add(tmp, tmp, t0); // tmp := tmp + *buffer_adr + + // Record the previous value + __ sd(pre_val, Address(tmp, 0)); + __ j(done); + + __ bind(runtime); + // save the live input values + RegSet saved = RegSet::of(pre_val); + if (tosca_live) saved += RegSet::of(x10); + if (obj != noreg) saved += RegSet::of(obj); + + __ push_reg(saved, sp); + + // Calling the runtime using the regular call_VM_leaf mechanism generates + // code (generated by InterpreterMacroAssember::call_VM_leaf_base) + // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL. + // + // If we care generating the pre-barrier without a frame (e.g. in the + // intrinsified Reference.get() routine) then ebp might be pointing to + // the caller frame and so this check will most likely fail at runtime. + // + // Expanding the call directly bypasses the generation of the check. + // So when we do not have have a full interpreter frame on the stack + // expand_call should be passed true. + if (expand_call) { + assert(pre_val != c_rarg1, "smashed arg"); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + } + + __ pop_reg(saved, sp); + + __ bind(done); +} + +void ShenandoahBarrierSetAssembler::resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp) { + assert(ShenandoahLoadRefBarrier || ShenandoahCASBarrier, "Should be enabled"); + + Label is_null; + __ beqz(dst, is_null); + resolve_forward_pointer_not_null(masm, dst, tmp); + __ bind(is_null); +} + +// IMPORTANT: This must preserve all registers, even t0 and t1, except those explicitely +// passed in. +void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp) { + assert(ShenandoahLoadRefBarrier || ShenandoahCASBarrier, "Should be enabled"); + // The below loads the mark word, checks if the lowest two bits are + // set, and if so, clear the lowest two bits and copy the result + // to dst. Otherwise it leaves dst alone. + // Implementing this is surprisingly awkward. I do it here by: + // - Inverting the mark word + // - Test lowest two bits == 0 + // - If so, set the lowest two bits + // - Invert the result back, and copy to dst + RegSet saved_regs = RegSet::of(t2); + bool borrow_reg = (tmp == noreg); + if (borrow_reg) { + // No free registers available. Make one useful. + tmp = t0; + if (tmp == dst) { + tmp = t1; + } + saved_regs += RegSet::of(tmp); + } + + assert_different_registers(tmp, dst, t2); + __ push_reg(saved_regs, sp); + + Label done; + __ ld(tmp, Address(dst, oopDesc::mark_offset_in_bytes())); + __ xori(tmp, tmp, -1); // eon with 0 is equivalent to XOR with -1 + __ andi(t2, tmp, markWord::lock_mask_in_place); + __ bnez(t2, done); + __ ori(tmp, tmp, markWord::marked_value); + __ xori(dst, tmp, -1); // eon with 0 is equivalent to XOR with -1 + __ bind(done); + + __ pop_reg(saved_regs, sp); +} + +void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, + Register dst, + Address load_addr, + DecoratorSet decorators) { + assert(ShenandoahLoadRefBarrier, "Should be enabled"); + assert(dst != t1 && load_addr.base() != t1, "need t1"); + assert_different_registers(load_addr.base(), t0, t1); + + bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); + bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); + bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); + bool is_native = ShenandoahBarrierSet::is_native_access(decorators); + bool is_narrow = UseCompressedOops && !is_native; + + Label heap_stable, not_cset; + __ enter(); + Address gc_state(xthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ lbu(t1, gc_state); + + // Check for heap stability + if (is_strong) { + __ andi(t1, t1, ShenandoahHeap::HAS_FORWARDED); + __ beqz(t1, heap_stable); + } else { + Label lrb; + __ andi(t0, t1, ShenandoahHeap::WEAK_ROOTS); + __ bnez(t0, lrb); + __ andi(t0, t1, ShenandoahHeap::HAS_FORWARDED); + __ beqz(t0, heap_stable); + __ bind(lrb); + } + + // use x11 for load address + Register result_dst = dst; + if (dst == x11) { + __ mv(t1, dst); + dst = t1; + } + + // Save x10 and x11, unless it is an output register + RegSet saved_regs = RegSet::of(x10, x11) - result_dst; + __ push_reg(saved_regs, sp); + __ la(x11, load_addr); + __ mv(x10, dst); + + // Test for in-cset + if (is_strong) { + __ li(t1, (uint64_t)ShenandoahHeap::in_cset_fast_test_addr()); + __ srli(t0, x10, ShenandoahHeapRegion::region_size_bytes_shift_jint()); + __ add(t1, t1, t0); + __ lbu(t1, Address(t1)); + __ andi(t0, t1, 1); + __ beqz(t0, not_cset); + } + + __ push_call_clobbered_registers(); + if (is_strong) { + if (is_narrow) { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); + } else { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); + } + } else if (is_weak) { + if (is_narrow) { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); + } else { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); + } + } else { + assert(is_phantom, "only remaining strength"); + assert(!is_narrow, "phantom access cannot be narrow"); + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); + } + __ jalr(ra); + __ mv(t0, x10); + __ pop_call_clobbered_registers(); + __ mv(x10, t0); + __ bind(not_cset); + __ mv(result_dst, x10); + __ pop_reg(saved_regs, sp); + + __ bind(heap_stable); + __ leave(); +} + +void ShenandoahBarrierSetAssembler::iu_barrier(MacroAssembler* masm, Register dst, Register tmp) { + if (ShenandoahIUBarrier) { + __ push_call_clobbered_registers(); + + satb_write_barrier_pre(masm, noreg, dst, xthread, tmp, true, false); + + __ pop_call_clobbered_registers(); + } +} + +// +// Arguments: +// +// Inputs: +// src: oop location to load from, might be clobbered +// +// Output: +// dst: oop loaded from src location +// +// Kill: +// x30 (tmp reg) +// +// Alias: +// dst: x30 (might use x30 as temporary output register to avoid clobbering src) +// +void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, + DecoratorSet decorators, + BasicType type, + Register dst, + Address src, + Register tmp1, + Register tmp_thread) { + // 1: non-reference load, no additional barrier is needed + if (!is_reference_type(type)) { + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + return; + } + + // 2: load a reference from src location and apply LRB if needed + if (ShenandoahBarrierSet::need_load_reference_barrier(decorators, type)) { + Register result_dst = dst; + + // Preserve src location for LRB + RegSet saved_regs; + if (dst == src.base()) { + dst = (src.base() == x28) ? x29 : x28; + saved_regs = RegSet::of(dst); + __ push_reg(saved_regs, sp); + } + assert_different_registers(dst, src.base()); + + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + + load_reference_barrier(masm, dst, src, decorators); + + if (dst != result_dst) { + __ mv(result_dst, dst); + dst = result_dst; + } + + if (saved_regs.bits() != 0) { + __ pop_reg(saved_regs, sp); + } + } else { + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + } + + // 3: apply keep-alive barrier if needed + if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { + __ enter(); + __ push_call_clobbered_registers(); + satb_write_barrier_pre(masm /* masm */, + noreg /* obj */, + dst /* pre_val */, + xthread /* thread */, + tmp1 /* tmp */, + true /* tosca_live */, + true /* expand_call */); + __ pop_call_clobbered_registers(); + __ leave(); + } +} + +void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + bool on_oop = is_reference_type(type); + if (!on_oop) { + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + return; + } + + // flatten object address if needed + if (dst.offset() == 0) { + if (dst.base() != x13) { + __ mv(x13, dst.base()); + } + } else { + __ la(x13, dst); + } + + shenandoah_write_barrier_pre(masm, + x13 /* obj */, + tmp2 /* pre_val */, + xthread /* thread */, + tmp1 /* tmp */, + val != noreg /* tosca_live */, + false /* expand_call */); + + if (val == noreg) { + BarrierSetAssembler::store_at(masm, decorators, type, Address(x13, 0), noreg, noreg, noreg); + } else { + iu_barrier(masm, val, tmp1); + // G1 barrier needs uncompressed oop for region cross check. + Register new_val = val; + if (UseCompressedOops) { + new_val = t1; + __ mv(new_val, val); + } + BarrierSetAssembler::store_at(masm, decorators, type, Address(x13, 0), val, noreg, noreg); + } +} + +void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath) { + Label done; + // Resolve jobject + BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, obj, tmp, slowpath); + + // Check for null. + __ beqz(obj, done); + + assert(obj != t1, "need t1"); + Address gc_state(jni_env, ShenandoahThreadLocalData::gc_state_offset() - JavaThread::jni_environment_offset()); + __ lbu(t1, gc_state); + + // Check for heap in evacuation phase + __ andi(t0, t1, ShenandoahHeap::EVACUATION); + __ bnez(t0, slowpath); + + __ bind(done); +} + +// Special Shenandoah CAS implementation that handles false negatives due +// to concurrent evacuation. The service is more complex than a +// traditional CAS operation because the CAS operation is intended to +// succeed if the reference at addr exactly matches expected or if the +// reference at addr holds a pointer to a from-space object that has +// been relocated to the location named by expected. There are two +// races that must be addressed: +// a) A parallel thread may mutate the contents of addr so that it points +// to a different object. In this case, the CAS operation should fail. +// b) A parallel thread may heal the contents of addr, replacing a +// from-space pointer held in addr with the to-space pointer +// representing the new location of the object. +// Upon entry to cmpxchg_oop, it is assured that new_val equals NULL +// or it refers to an object that is not being evacuated out of +// from-space, or it refers to the to-space version of an object that +// is being evacuated out of from-space. +// +// By default the value held in the result register following execution +// of the generated code sequence is 0 to indicate failure of CAS, +// non-zero to indicate success. If is_cae, the result is the value most +// recently fetched from addr rather than a boolean success indicator. +// +// Clobbers t0, t1 +void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, + Register addr, + Register expected, + Register new_val, + Assembler::Aqrl acquire, + Assembler::Aqrl release, + bool is_cae, + Register result) { + bool is_narrow = UseCompressedOops; + Assembler::operand_size size = is_narrow ? Assembler::uint32 : Assembler::int64; + + assert_different_registers(addr, expected, t0, t1); + assert_different_registers(addr, new_val, t0, t1); + + Label retry, success, fail, done; + + __ bind(retry); + + // Step1: Try to CAS. + __ cmpxchg(addr, expected, new_val, size, acquire, release, /* result */ t1); + + // If success, then we are done. + __ beq(expected, t1, success); + + // Step2: CAS failed, check the forwared pointer. + __ mv(t0, t1); + + if (is_narrow) { + __ decode_heap_oop(t0, t0); + } + resolve_forward_pointer(masm, t0); + + __ encode_heap_oop(t0, t0); + + // Report failure when the forwarded oop was not expected. + __ bne(t0, expected, fail); + + // Step 3: CAS again using the forwarded oop. + __ cmpxchg(addr, t1, new_val, size, acquire, release, /* result */ t0); + + // Retry when failed. + __ bne(t0, t1, retry); + + __ bind(success); + if (is_cae) { + __ mv(result, expected); + } else { + __ addi(result, zr, 1); + } + __ j(done); + + __ bind(fail); + if (is_cae) { + __ mv(result, t0); + } else { + __ mv(result, zr); + } + + __ bind(done); +} + +#undef __ + +#ifdef COMPILER1 + +#define __ ce->masm()-> + +void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub) { + ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); + // At this point we know that marking is in progress. + // If do_load() is true then we have to emit the + // load of the previous value; otherwise it has already + // been loaded into _pre_val. + __ bind(*stub->entry()); + + assert(stub->pre_val()->is_register(), "Precondition."); + + Register pre_val_reg = stub->pre_val()->as_register(); + + if (stub->do_load()) { + ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); + } + __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); + ce->store_parameter(stub->pre_val()->as_register(), 0); + __ far_call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin())); + __ j(*stub->continuation()); +} + +void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, + ShenandoahLoadReferenceBarrierStub* stub) { + ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); + __ bind(*stub->entry()); + + DecoratorSet decorators = stub->decorators(); + bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); + bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); + bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); + bool is_native = ShenandoahBarrierSet::is_native_access(decorators); + + Register obj = stub->obj()->as_register(); + Register res = stub->result()->as_register(); + Register addr = stub->addr()->as_pointer_register(); + Register tmp1 = stub->tmp1()->as_register(); + Register tmp2 = stub->tmp2()->as_register(); + + assert(res == x10, "result must arrive in x10"); + assert_different_registers(tmp1, tmp2, t0); + + if (res != obj) { + __ mv(res, obj); + } + + if (is_strong) { + // Check for object in cset. + __ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr()); + __ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint()); + __ add(tmp2, tmp2, tmp1); + __ lbu(tmp2, Address(tmp2)); + __ beqz(tmp2, *stub->continuation(), true /* is_far */); + } + + ce->store_parameter(res, 0); + ce->store_parameter(addr, 1); + + if (is_strong) { + if (is_native) { + __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin())); + } else { + __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_rt_code_blob()->code_begin())); + } + } else if (is_weak) { + __ far_call(RuntimeAddress(bs->load_reference_barrier_weak_rt_code_blob()->code_begin())); + } else { + assert(is_phantom, "only remaining strength"); + __ far_call(RuntimeAddress(bs->load_reference_barrier_phantom_rt_code_blob()->code_begin())); + } + + __ j(*stub->continuation()); +} + +#undef __ + +#define __ sasm-> + +void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) { + __ prologue("shenandoah_pre_barrier", false); + + // arg0 : previous value of memory + + BarrierSet* bs = BarrierSet::barrier_set(); + + const Register pre_val = x10; + const Register thread = xthread; + const Register tmp = t0; + + Address queue_index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); + + Label done; + Label runtime; + + // Is marking still active? + Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ lb(tmp, gc_state); + __ andi(tmp, tmp, ShenandoahHeap::MARKING); + __ beqz(tmp, done); + + // Can we store original value in the thread's buffer? + __ ld(tmp, queue_index); + __ beqz(tmp, runtime); + + __ sub(tmp, tmp, wordSize); + __ sd(tmp, queue_index); + __ ld(t1, buffer); + __ add(tmp, tmp, t1); + __ load_parameter(0, t1); + __ sd(t1, Address(tmp, 0)); + __ j(done); + + __ bind(runtime); + __ push_call_clobbered_registers(); + __ load_parameter(0, pre_val); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ pop_call_clobbered_registers(); + __ bind(done); + + __ epilogue(); +} + +void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, + DecoratorSet decorators) { + __ prologue("shenandoah_load_reference_barrier", false); + // arg0 : object to be resolved + + __ push_call_clobbered_registers(); + __ load_parameter(0, x10); + __ load_parameter(1, x11); + + bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); + bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); + bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); + bool is_native = ShenandoahBarrierSet::is_native_access(decorators); + if (is_strong) { + if (is_native) { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); + } else { + if (UseCompressedOops) { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); + } else { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); + } + } + } else if (is_weak) { + assert(!is_native, "weak must not be called off-heap"); + if (UseCompressedOops) { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); + } else { + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); + } + } else { + assert(is_phantom, "only remaining strength"); + assert(is_native, "phantom must only be called off-heap"); + __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_phantom); + } + __ jalr(ra); + __ mv(t0, x10); + __ pop_call_clobbered_registers(); + __ mv(x10, t0); + + __ epilogue(); +} + +#undef __ + +#endif // COMPILER1 diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a705f49766777d5207d0695703375379b97c92c3 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#ifdef COMPILER1 +class LIR_Assembler; +class ShenandoahPreBarrierStub; +class ShenandoahLoadReferenceBarrierStub; +class StubAssembler; +#endif +class StubCodeGenerator; + +class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { +private: + + void satb_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + void shenandoah_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + + void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg); + void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg); + void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr, DecoratorSet decorators); + +public: + + void iu_barrier(MacroAssembler* masm, Register dst, Register tmp); + +#ifdef COMPILER1 + void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); + void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub); + void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); + void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators); +#endif + + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs); + + 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); + + virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath); + + void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, + Assembler::Aqrl acquire, Assembler::Aqrl release, bool is_cae, Register result); +}; + +#endif // CPU_RISCV_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad new file mode 100644 index 0000000000000000000000000000000000000000..6c855f23c2af1b8bf850086fb9b670893c6aa145 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad @@ -0,0 +1,285 @@ +// +// Copyright (c) 2018, Red Hat, Inc. All rights reserved. +// Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +source_hpp %{ +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" +%} + +instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + + format %{ + "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapP_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + + format %{ + "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapN_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + + format %{ + "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapPAcq_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + + format %{ + "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapNAcq_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + effect(TEMP_DEF res, TEMP tmp, KILL cr); + + format %{ + "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeN_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + true /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP_DEF res, TEMP tmp, KILL cr); + format %{ + "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndExchangeP_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + true /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + format %{ + "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapN_shenandoah" + "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP_DEF res, TEMP tmp, KILL cr); + format %{ + "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + true /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP_DEF res, TEMP tmp, KILL cr); + format %{ + "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + true /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + format %{ + "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapP_shenandoah" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + format %{ + "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapNAcq_shenandoah" + "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + predicate(needs_acquiring_load_reserved(n)); + match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); + + effect(TEMP tmp, KILL cr); + format %{ + "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapPAcq_shenandoah" + "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mv(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, + Assembler::aq /* acquire */, Assembler::rl /* release */, + false /* is_cae */, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d3f4d4d7741b0f99c324a9c2b0b70e1f80d0170 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "code/codeBlob.hpp" +#include "code/vmreg.inline.hpp" +#include "gc/z/zBarrier.inline.hpp" +#include "gc/z/zBarrierSet.hpp" +#include "gc/z/zBarrierSetAssembler.hpp" +#include "gc/z/zBarrierSetRuntime.hpp" +#include "gc/z/zThreadLocalData.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" +#ifdef COMPILER1 +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" +#include "gc/z/c1/zBarrierSetC1.hpp" +#endif // COMPILER1 +#ifdef COMPILER2 +#include "gc/z/c2/zBarrierSetC2.hpp" +#endif // COMPILER2 + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#undef __ +#define __ masm-> + +void ZBarrierSetAssembler::load_at(MacroAssembler* masm, + DecoratorSet decorators, + BasicType type, + Register dst, + Address src, + Register tmp1, + Register tmp_thread) { + if (!ZBarrierSet::barrier_needed(decorators, type)) { + // Barrier not needed + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + return; + } + + assert_different_registers(t1, src.base()); + assert_different_registers(t0, t1, dst); + + Label done; + + // Load bad mask into temp register. + __ la(t0, src); + __ ld(t1, address_bad_mask_from_thread(xthread)); + __ ld(dst, Address(t0)); + + // Test reference against bad mask. If mask bad, then we need to fix it up. + __ andr(t1, dst, t1); + __ beqz(t1, done); + + __ enter(); + + __ push_call_clobbered_registers_except(RegSet::of(dst)); + + if (c_rarg0 != dst) { + __ mv(c_rarg0, dst); + } + + __ mv(c_rarg1, t0); + + __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); + + // Make sure dst has the return value. + if (dst != x10) { + __ mv(dst, x10); + } + + __ pop_call_clobbered_registers_except(RegSet::of(dst)); + __ leave(); + + __ bind(done); +} + +#ifdef ASSERT + +void ZBarrierSetAssembler::store_at(MacroAssembler* masm, + DecoratorSet decorators, + BasicType type, + Address dst, + Register val, + Register tmp1, + Register tmp2) { + // Verify value + if (is_reference_type(type)) { + // Note that src could be noreg, which means we + // are storing null and can skip verification. + if (val != noreg) { + Label done; + + // tmp1 and tmp2 are often set to noreg. + RegSet savedRegs = RegSet::of(t0); + __ push_reg(savedRegs, sp); + + __ ld(t0, address_bad_mask_from_thread(xthread)); + __ andr(t0, val, t0); + __ beqz(t0, done); + __ stop("Verify oop store failed"); + __ should_not_reach_here(); + __ bind(done); + __ pop_reg(savedRegs, sp); + } + } + + // Store value + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); +} + +#endif // ASSERT + +void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, + DecoratorSet decorators, + bool is_oop, + Register src, + Register dst, + Register count, + RegSet saved_regs) { + if (!is_oop) { + // Barrier not needed + return; + } + + BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {"); + + assert_different_registers(src, count, t0); + + __ push_reg(saved_regs, sp); + + if (count == c_rarg0 && src == c_rarg1) { + // exactly backwards!! + __ xorr(c_rarg0, c_rarg0, c_rarg1); + __ xorr(c_rarg1, c_rarg0, c_rarg1); + __ xorr(c_rarg0, c_rarg0, c_rarg1); + } else { + __ mv(c_rarg0, src); + __ mv(c_rarg1, count); + } + + __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2); + + __ pop_reg(saved_regs, sp); + + BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue"); +} + +void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, + Register jni_env, + Register robj, + Register tmp, + Label& slowpath) { + BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {"); + + assert_different_registers(jni_env, robj, tmp); + + // Resolve jobject + BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, robj, tmp, slowpath); + + // Compute the offset of address bad mask from the field of jni_environment + long int bad_mask_relative_offset = (long int) (in_bytes(ZThreadLocalData::address_bad_mask_offset()) - + in_bytes(JavaThread::jni_environment_offset())); + + // Load the address bad mask + __ ld(tmp, Address(jni_env, bad_mask_relative_offset)); + + // Check address bad mask + __ andr(tmp, robj, tmp); + __ bnez(tmp, slowpath); + + BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native"); +} + +#ifdef COMPILER2 + +OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { + if (!OptoReg::is_reg(opto_reg)) { + return OptoReg::Bad; + } + + const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); + if (vm_reg->is_FloatRegister()) { + return opto_reg & ~1; + } + + return opto_reg; +} + +#undef __ +#define __ _masm-> + +class ZSaveLiveRegisters { +private: + MacroAssembler* const _masm; + RegSet _gp_regs; + FloatRegSet _fp_regs; + VectorRegSet _vp_regs; + +public: + void initialize(ZLoadBarrierStubC2* stub) { + // Record registers that needs to be saved/restored + RegMaskIterator rmi(stub->live()); + while (rmi.has_next()) { + const OptoReg::Name opto_reg = rmi.next(); + if (OptoReg::is_reg(opto_reg)) { + const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); + if (vm_reg->is_Register()) { + _gp_regs += RegSet::of(vm_reg->as_Register()); + } else if (vm_reg->is_FloatRegister()) { + _fp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); + } else if (vm_reg->is_VectorRegister()) { + const VMReg vm_reg_base = OptoReg::as_VMReg(opto_reg & ~(VectorRegisterImpl::max_slots_per_register - 1)); + _vp_regs += VectorRegSet::of(vm_reg_base->as_VectorRegister()); + } else { + fatal("Unknown register type"); + } + } + } + + // Remove C-ABI SOE registers, tmp regs and _ref register that will be updated + _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2) + RegSet::of(x8, x9) + RegSet::of(x5, stub->ref()); + } + + ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : + _masm(masm), + _gp_regs(), + _fp_regs(), + _vp_regs() { + // Figure out what registers to save/restore + initialize(stub); + + // Save registers + __ push_reg(_gp_regs, sp); + __ push_fp(_fp_regs, sp); + __ push_vp(_vp_regs, sp); + } + + ~ZSaveLiveRegisters() { + // Restore registers + __ pop_vp(_vp_regs, sp); + __ pop_fp(_fp_regs, sp); + __ pop_reg(_gp_regs, sp); + } +}; + +class ZSetupArguments { +private: + MacroAssembler* const _masm; + const Register _ref; + const Address _ref_addr; + +public: + ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : + _masm(masm), + _ref(stub->ref()), + _ref_addr(stub->ref_addr()) { + + // Setup arguments + if (_ref_addr.base() == noreg) { + // No self healing + if (_ref != c_rarg0) { + __ mv(c_rarg0, _ref); + } + __ mv(c_rarg1, zr); + } else { + // Self healing + if (_ref == c_rarg0) { + // _ref is already at correct place + __ la(c_rarg1, _ref_addr); + } else if (_ref != c_rarg1) { + // _ref is in wrong place, but not in c_rarg1, so fix it first + __ la(c_rarg1, _ref_addr); + __ mv(c_rarg0, _ref); + } else if (_ref_addr.base() != c_rarg0) { + assert(_ref == c_rarg1, "Mov ref first, vacating c_rarg0"); + __ mv(c_rarg0, _ref); + __ la(c_rarg1, _ref_addr); + } else { + assert(_ref == c_rarg1, "Need to vacate c_rarg1 and _ref_addr is using c_rarg0"); + if (_ref_addr.base() == c_rarg0) { + __ mv(t1, c_rarg1); + __ la(c_rarg1, _ref_addr); + __ mv(c_rarg0, t1); + } else { + ShouldNotReachHere(); + } + } + } + } + + ~ZSetupArguments() { + // Transfer result + if (_ref != x10) { + __ mv(_ref, x10); + } + } +}; + +#undef __ +#define __ masm-> + +void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { + BLOCK_COMMENT("ZLoadBarrierStubC2"); + + // Stub entry + __ bind(*stub->entry()); + + { + ZSaveLiveRegisters save_live_registers(masm, stub); + ZSetupArguments setup_arguments(masm, stub); + int32_t offset = 0; + __ la_patchable(t0, stub->slow_path(), offset); + __ jalr(x1, t0, offset); + } + + // Stub exit + __ j(*stub->continuation()); +} + +#undef __ + +#endif // COMPILER2 + +#ifdef COMPILER1 +#undef __ +#define __ ce->masm()-> + +void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce, + LIR_Opr ref) const { + assert_different_registers(xthread, ref->as_register(), t1); + __ ld(t1, address_bad_mask_from_thread(xthread)); + __ andr(t1, t1, ref->as_register()); +} + +void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce, + ZLoadBarrierStubC1* stub) const { + // Stub entry + __ bind(*stub->entry()); + + Register ref = stub->ref()->as_register(); + Register ref_addr = noreg; + Register tmp = noreg; + + if (stub->tmp()->is_valid()) { + // Load address into tmp register + ce->leal(stub->ref_addr(), stub->tmp()); + ref_addr = tmp = stub->tmp()->as_pointer_register(); + } else { + // Address already in register + ref_addr = stub->ref_addr()->as_address_ptr()->base()->as_pointer_register(); + } + + assert_different_registers(ref, ref_addr, noreg); + + // Save x10 unless it is the result or tmp register + // Set up SP to accomodate parameters and maybe x10. + if (ref != x10 && tmp != x10) { + __ sub(sp, sp, 32); + __ sd(x10, Address(sp, 16)); + } else { + __ sub(sp, sp, 16); + } + + // Setup arguments and call runtime stub + ce->store_parameter(ref_addr, 1); + ce->store_parameter(ref, 0); + + __ far_call(stub->runtime_stub()); + + // Verify result + __ verify_oop(x10, "Bad oop"); + + + // Move result into place + if (ref != x10) { + __ mv(ref, x10); + } + + // Restore x10 unless it is the result or tmp register + if (ref != x10 && tmp != x10) { + __ ld(x10, Address(sp, 16)); + __ add(sp, sp, 32); + } else { + __ add(sp, sp, 16); + } + + // Stub exit + __ j(*stub->continuation()); +} + +#undef __ +#define __ sasm-> + +void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, + DecoratorSet decorators) const { + __ prologue("zgc_load_barrier stub", false); + + __ push_call_clobbered_registers_except(RegSet::of(x10)); + + // Setup arguments + __ load_parameter(0, c_rarg0); + __ load_parameter(1, c_rarg1); + + __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); + + __ pop_call_clobbered_registers_except(RegSet::of(x10)); + + __ epilogue(); +} + +#undef __ +#endif // COMPILER1 diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dc07ab635fed9d6077e0350d03f52453922ddbd6 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP +#define CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP + +#include "code/vmreg.hpp" +#include "oops/accessDecorators.hpp" +#ifdef COMPILER2 +#include "opto/optoreg.hpp" +#endif // COMPILER2 + +#ifdef COMPILER1 +class LIR_Assembler; +class LIR_Opr; +class StubAssembler; +class ZLoadBarrierStubC1; +#endif // COMPILER1 + +#ifdef COMPILER2 +class Node; +class ZLoadBarrierStubC2; +#endif // COMPILER2 + +class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase { +public: + virtual void load_at(MacroAssembler* masm, + DecoratorSet decorators, + BasicType type, + Register dst, + Address src, + Register tmp1, + Register tmp_thread); + +#ifdef ASSERT + virtual void store_at(MacroAssembler* masm, + DecoratorSet decorators, + BasicType type, + Address dst, + Register val, + Register tmp1, + Register tmp2); +#endif // ASSERT + + virtual void arraycopy_prologue(MacroAssembler* masm, + DecoratorSet decorators, + bool is_oop, + Register src, + Register dst, + Register count, + RegSet saved_regs); + + virtual void try_resolve_jobject_in_native(MacroAssembler* masm, + Register jni_env, + Register robj, + Register tmp, + Label& slowpath); + +#ifdef COMPILER1 + void generate_c1_load_barrier_test(LIR_Assembler* ce, + LIR_Opr ref) const; + + void generate_c1_load_barrier_stub(LIR_Assembler* ce, + ZLoadBarrierStubC1* stub) const; + + void generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, + DecoratorSet decorators) const; +#endif // COMPILER1 + +#ifdef COMPILER2 + OptoReg::Name refine_register(const Node* node, + OptoReg::Name opto_reg); + + void generate_c2_load_barrier_stub(MacroAssembler* masm, + ZLoadBarrierStubC2* stub) const; +#endif // COMPILER2 +}; + +#endif // CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d14997790afaa108ccc80e28562d2e9d822be7b4 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/shared/gcLogPrecious.hpp" +#include "gc/shared/gc_globals.hpp" +#include "gc/z/zGlobals.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" + +#ifdef LINUX +#include +#endif // LINUX + +// +// The heap can have three different layouts, depending on the max heap size. +// +// Address Space & Pointer Layout 1 +// -------------------------------- +// +// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) +// . . +// . . +// . . +// +--------------------------------+ 0x0000014000000000 (20TB) +// | Remapped View | +// +--------------------------------+ 0x0000010000000000 (16TB) +// . . +// +--------------------------------+ 0x00000c0000000000 (12TB) +// | Marked1 View | +// +--------------------------------+ 0x0000080000000000 (8TB) +// | Marked0 View | +// +--------------------------------+ 0x0000040000000000 (4TB) +// . . +// +--------------------------------+ 0x0000000000000000 +// +// 6 4 4 4 4 +// 3 6 5 2 1 0 +// +--------------------+----+-----------------------------------------------+ +// |00000000 00000000 00|1111|11 11111111 11111111 11111111 11111111 11111111| +// +--------------------+----+-----------------------------------------------+ +// | | | +// | | * 41-0 Object Offset (42-bits, 4TB address space) +// | | +// | * 45-42 Metadata Bits (4-bits) 0001 = Marked0 (Address view 4-8TB) +// | 0010 = Marked1 (Address view 8-12TB) +// | 0100 = Remapped (Address view 16-20TB) +// | 1000 = Finalizable (Address view N/A) +// | +// * 63-46 Fixed (18-bits, always zero) +// +// +// Address Space & Pointer Layout 2 +// -------------------------------- +// +// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) +// . . +// . . +// . . +// +--------------------------------+ 0x0000280000000000 (40TB) +// | Remapped View | +// +--------------------------------+ 0x0000200000000000 (32TB) +// . . +// +--------------------------------+ 0x0000180000000000 (24TB) +// | Marked1 View | +// +--------------------------------+ 0x0000100000000000 (16TB) +// | Marked0 View | +// +--------------------------------+ 0x0000080000000000 (8TB) +// . . +// +--------------------------------+ 0x0000000000000000 +// +// 6 4 4 4 4 +// 3 7 6 3 2 0 +// +------------------+-----+------------------------------------------------+ +// |00000000 00000000 0|1111|111 11111111 11111111 11111111 11111111 11111111| +// +-------------------+----+------------------------------------------------+ +// | | | +// | | * 42-0 Object Offset (43-bits, 8TB address space) +// | | +// | * 46-43 Metadata Bits (4-bits) 0001 = Marked0 (Address view 8-16TB) +// | 0010 = Marked1 (Address view 16-24TB) +// | 0100 = Remapped (Address view 32-40TB) +// | 1000 = Finalizable (Address view N/A) +// | +// * 63-47 Fixed (17-bits, always zero) +// +// +// Address Space & Pointer Layout 3 +// -------------------------------- +// +// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) +// . . +// . . +// . . +// +--------------------------------+ 0x0000500000000000 (80TB) +// | Remapped View | +// +--------------------------------+ 0x0000400000000000 (64TB) +// . . +// +--------------------------------+ 0x0000300000000000 (48TB) +// | Marked1 View | +// +--------------------------------+ 0x0000200000000000 (32TB) +// | Marked0 View | +// +--------------------------------+ 0x0000100000000000 (16TB) +// . . +// +--------------------------------+ 0x0000000000000000 +// +// 6 4 4 4 4 +// 3 8 7 4 3 0 +// +------------------+----+-------------------------------------------------+ +// |00000000 00000000 |1111|1111 11111111 11111111 11111111 11111111 11111111| +// +------------------+----+-------------------------------------------------+ +// | | | +// | | * 43-0 Object Offset (44-bits, 16TB address space) +// | | +// | * 47-44 Metadata Bits (4-bits) 0001 = Marked0 (Address view 16-32TB) +// | 0010 = Marked1 (Address view 32-48TB) +// | 0100 = Remapped (Address view 64-80TB) +// | 1000 = Finalizable (Address view N/A) +// | +// * 63-48 Fixed (16-bits, always zero) +// + +// Default value if probing is not implemented for a certain platform: 128TB +static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; +// Minimum value returned, if probing fails: 64GB +static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; + +static size_t probe_valid_max_address_bit() { +#ifdef LINUX + size_t max_address_bit = 0; + const size_t page_size = os::vm_page_size(); + for (size_t i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT; --i) { + const uintptr_t base_addr = ((uintptr_t) 1U) << i; + if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) { + // msync suceeded, the address is valid, and maybe even already mapped. + max_address_bit = i; + break; + } + if (errno != ENOMEM) { + // Some error occured. This should never happen, but msync + // has some undefined behavior, hence ignore this bit. +#ifdef ASSERT + fatal("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); +#else // ASSERT + log_warning_p(gc)("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); +#endif // ASSERT + continue; + } + // Since msync failed with ENOMEM, the page might not be mapped. + // Try to map it, to see if the address is valid. + void* const result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); + if (result_addr != MAP_FAILED) { + munmap(result_addr, page_size); + } + if ((uintptr_t) result_addr == base_addr) { + // address is valid + max_address_bit = i; + break; + } + } + if (max_address_bit == 0) { + // probing failed, allocate a very high page and take that bit as the maximum + const uintptr_t high_addr = ((uintptr_t) 1U) << DEFAULT_MAX_ADDRESS_BIT; + void* const result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); + if (result_addr != MAP_FAILED) { + max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1; + munmap(result_addr, page_size); + } + } + log_info_p(gc, init)("Probing address space for the highest valid bit: " SIZE_FORMAT, max_address_bit); + return MAX2(max_address_bit, MINIMUM_MAX_ADDRESS_BIT); +#else // LINUX + return DEFAULT_MAX_ADDRESS_BIT; +#endif // LINUX +} + +size_t ZPlatformAddressOffsetBits() { + const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; + const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; + const size_t min_address_offset_bits = max_address_offset_bits - 2; + const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset_bits = log2i_exact(address_offset); + return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); +} + +size_t ZPlatformAddressMetadataShift() { + return ZPlatformAddressOffsetBits(); +} diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f20ecd9b073c02b5a2da76d9cf5b0c1faf765dde --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP +#define CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP + +const size_t ZPlatformGranuleSizeShift = 21; // 2MB +const size_t ZPlatformHeapViews = 3; +const size_t ZPlatformCacheLineSize = 64; + +size_t ZPlatformAddressOffsetBits(); +size_t ZPlatformAddressMetadataShift(); + +#endif // CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad b/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad new file mode 100644 index 0000000000000000000000000000000000000000..6b6f87814a56ef1b1d11264c22dd7b8194a1fa28 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad @@ -0,0 +1,233 @@ +// +// Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// + +source_hpp %{ + +#include "gc/shared/gc_globals.hpp" +#include "gc/z/c2/zBarrierSetC2.hpp" +#include "gc/z/zThreadLocalData.hpp" + +%} + +source %{ + +static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, int barrier_data) { + if (barrier_data == ZLoadBarrierElided) { + return; + } + ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); + __ ld(tmp, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); + __ andr(tmp, tmp, ref); + __ bnez(tmp, *stub->entry(), true /* far */); + __ bind(*stub->continuation()); +} + +static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { + ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, ZLoadBarrierStrong); + __ j(*stub->entry()); + __ bind(*stub->continuation()); +} + +%} + +// Load Pointer +instruct zLoadP(iRegPNoSp dst, memory mem) +%{ + match(Set dst (LoadP mem)); + predicate(UseZGC && (n->as_Load()->barrier_data() != 0)); + effect(TEMP dst); + + ins_cost(4 * DEFAULT_COST); + + format %{ "ld $dst, $mem, #@zLoadP" %} + + ins_encode %{ + const Address ref_addr (as_Register($mem$$base), $mem$$disp); + __ ld($dst$$Register, ref_addr); + z_load_barrier(_masm, this, ref_addr, $dst$$Register, t0 /* tmp */, barrier_data()); + %} + + ins_pipe(iload_reg_mem); +%} + +instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); + effect(KILL cr, TEMP_DEF res); + + ins_cost(2 * VOLATILE_REF_COST); + + format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapP\n\t" + "mv $res, $res == $oldval" %} + + ins_encode %{ + Label failed; + guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result_as_bool */); + __ beqz($res$$Register, failed); + __ mv(t0, $oldval$$Register); + __ bind(failed); + if (barrier_data() != ZLoadBarrierElided) { + Label good; + __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); + __ andr(t1, t1, t0); + __ beqz(t1, good); + z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result_as_bool */); + __ bind(good); + } + %} + + ins_pipe(pipe_slow); +%} + +instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong)); + effect(KILL cr, TEMP_DEF res); + + ins_cost(2 * VOLATILE_REF_COST); + + format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapPAcq\n\t" + "mv $res, $res == $oldval" %} + + ins_encode %{ + Label failed; + guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result_as_bool */); + __ beqz($res$$Register, failed); + __ mv(t0, $oldval$$Register); + __ bind(failed); + if (barrier_data() != ZLoadBarrierElided) { + Label good; + __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); + __ andr(t1, t1, t0); + __ beqz(t1, good); + z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result_as_bool */); + __ bind(good); + } + %} + + ins_pipe(pipe_slow); +%} + +instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); + effect(TEMP_DEF res); + + ins_cost(2 * VOLATILE_REF_COST); + + format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangeP" %} + + ins_encode %{ + guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); + if (barrier_data() != ZLoadBarrierElided) { + Label good; + __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); + __ andr(t0, t0, $res$$Register); + __ beqz(t0, good); + z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); + __ bind(good); + } + %} + + ins_pipe(pipe_slow); +%} + +instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + predicate(UseZGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); + effect(TEMP_DEF res); + + ins_cost(2 * VOLATILE_REF_COST); + + format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangePAcq" %} + + ins_encode %{ + guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); + if (barrier_data() != ZLoadBarrierElided) { + Label good; + __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); + __ andr(t0, t0, $res$$Register); + __ beqz(t0, good); + z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); + __ bind(good); + } + %} + + ins_pipe(pipe_slow); +%} + +instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ + match(Set prev (GetAndSetP mem newv)); + predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0); + effect(TEMP_DEF prev, KILL cr); + + ins_cost(2 * VOLATILE_REF_COST); + + format %{ "atomic_xchg $prev, $newv, [$mem], #@zGetAndSetP" %} + + ins_encode %{ + __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base)); + z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); + %} + + ins_pipe(pipe_serial); +%} + +instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ + match(Set prev (GetAndSetP mem newv)); + predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() != 0)); + effect(TEMP_DEF prev, KILL cr); + + ins_cost(VOLATILE_REF_COST); + + format %{ "atomic_xchg_acq $prev, $newv, [$mem], #@zGetAndSetPAcq" %} + + ins_encode %{ + __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base)); + z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); + %} + ins_pipe(pipe_serial); +%} diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2936837d95183b3ca1192afa6913279312acc0ac --- /dev/null +++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP +#define CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP + +const int StackAlignmentInBytes = 16; + +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are extended to 64 bits. +const bool CCallingConventionRequiresIntsAsLongs = false; + +// RISCV has adopted a multicopy atomic model closely following +// that of ARMv8. +#define CPU_MULTI_COPY_ATOMIC + +// To be safe, we deoptimize when we come across an access that needs +// patching. This is similar to what is done on aarch64. +#define DEOPTIMIZE_WHEN_PATCHING + +#define SUPPORTS_NATIVE_CX8 + +#define SUPPORT_RESERVED_STACK_AREA + +#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false + +#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY + +#endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..30e3a8779b88cb07382db14d932983118285fb11 --- /dev/null +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_GLOBALS_RISCV_HPP +#define CPU_RISCV_GLOBALS_RISCV_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + +define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks +define_pd_global(bool, TrapBasedNullChecks, false); +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast + +define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. +define_pd_global(intx, CodeEntryAlignment, 64); +define_pd_global(intx, OptoLoopAlignment, 16); + +#define DEFAULT_STACK_YELLOW_PAGES (2) +#define DEFAULT_STACK_RED_PAGES (1) +// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the +// stack if compiled for unix and LP64. To pass stack overflow tests we need +// 20 shadow pages. +#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5)) +#define DEFAULT_STACK_RESERVED_PAGES (1) + +#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES +#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES +#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES +#define MIN_STACK_RESERVED_PAGES (0) + +define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES); +define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES); +define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES); +define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES); + +define_pd_global(bool, RewriteBytecodes, true); +define_pd_global(bool, RewriteFrequentPairs, true); + +define_pd_global(bool, PreserveFramePointer, false); + +define_pd_global(uintx, TypeProfileLevel, 111); + +define_pd_global(bool, CompactStrings, true); + +// Clear short arrays bigger than one word in an arch-specific way +define_pd_global(intx, InitArrayShortSize, BytesPerLong); + +define_pd_global(intx, InlineSmallCode, 1000); + +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ + \ + product(bool, NearCpool, true, \ + "constant pool is close to instructions") \ + product(intx, BlockZeroingLowLimit, 256, \ + "Minimum size in bytes when block zeroing will be used") \ + range(1, max_jint) \ + product(bool, TraceTraps, false, "Trace all traps the signal handler") \ + /* For now we're going to be safe and add the I/O bits to userspace fences. */ \ + product(bool, UseConservativeFence, true, \ + "Extend i for r and o for w in the pred/succ flags of fence;" \ + "Extend fence.i to fence.i + fence.") \ + product(bool, AvoidUnalignedAccesses, true, \ + "Avoid generating unaligned memory accesses") \ + product(bool, UseRVV, false, EXPERIMENTAL, "Use RVV instructions") \ + product(bool, UseRVC, false, EXPERIMENTAL, "Use RVC instructions") \ + product(bool, UseZba, false, EXPERIMENTAL, "Use Zba instructions") \ + product(bool, UseZbb, false, EXPERIMENTAL, "Use Zbb instructions") \ + product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \ + "Use RVV instructions for left/right shift of BigInteger") + +#endif // CPU_RISCV_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc93103dc556785d3761393aea17f5fce5516cad --- /dev/null +++ b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/icBuffer.hpp" +#include "gc/shared/collectedHeap.inline.hpp" +#include "interpreter/bytecodes.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/oop.inline.hpp" + +int InlineCacheBuffer::ic_stub_code_size() { + // 6: auipc + ld + auipc + jalr + address(2 * instruction_size) + // 5: auipc + ld + j + address(2 * instruction_size) + return (MacroAssembler::far_branches() ? 6 : 5) * NativeInstruction::instruction_size; +} + +#define __ masm-> + +void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { + assert_cond(code_begin != NULL && entry_point != NULL); + ResourceMark rm; + CodeBuffer code(code_begin, ic_stub_code_size()); + MacroAssembler* masm = new MacroAssembler(&code); + // Note: even though the code contains an embedded value, we do not need reloc info + // because + // (1) the value is old (i.e., doesn't matter for scavenges) + // (2) these ICStubs are removed *before* a GC happens, so the roots disappear + + address start = __ pc(); + Label l; + __ ld(t1, l); + __ far_jump(ExternalAddress(entry_point)); + __ align(wordSize); + __ bind(l); + __ emit_int64((intptr_t)cached_value); + // Only need to invalidate the 1st two instructions - not the whole ic stub + ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size()); + assert(__ pc() - start == ic_stub_code_size(), "must be"); +} + +address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { + NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object + NativeJump* jump = nativeJump_at(move->next_instruction_address()); + return jump->jump_destination(); +} + + +void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { + // The word containing the cached value is at the end of this IC buffer + uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize); + void* o = (void*)*p; + return o; +} diff --git a/src/hotspot/cpu/riscv/icache_riscv.cpp b/src/hotspot/cpu/riscv/icache_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..922a80f9f3e0050288387c66b40b7e1543b88e0b --- /dev/null +++ b/src/hotspot/cpu/riscv/icache_riscv.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "runtime/icache.hpp" + +#define __ _masm-> + +static int icache_flush(address addr, int lines, int magic) { + os::icache_flush((long int) addr, (long int) (addr + (lines << ICache::log2_line_size))); + return magic; +} + +void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) { + address start = (address)icache_flush; + *flush_icache_stub = (ICache::flush_icache_stub_t)start; + + // ICache::invalidate_range() contains explicit condition that the first + // call is invoked on the generated icache flush stub code range. + ICache::invalidate_range(start, 0); + + { + StubCodeMark mark(this, "ICache", "fake_stub_for_inlined_icache_flush"); + __ ret(); + } +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/icache_riscv.hpp b/src/hotspot/cpu/riscv/icache_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5bf40ca820485a482e132e6b4d3cb12ce8ac2c8d --- /dev/null +++ b/src/hotspot/cpu/riscv/icache_riscv.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_ICACHE_RISCV_HPP +#define CPU_RISCV_ICACHE_RISCV_HPP + +// Interface for updating the instruction cache. Whenever the VM +// modifies code, part of the processor instruction cache potentially +// has to be flushed. + +class ICache : public AbstractICache { +public: + enum { + stub_size = 16, // Size of the icache flush stub in bytes + line_size = BytesPerWord, // conservative + log2_line_size = LogBytesPerWord // log2(line_size) + }; +}; + +#endif // CPU_RISCV_ICACHE_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d12dcb2af1957a6aac88c6541841018fdbd0e65f --- /dev/null +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -0,0 +1,1940 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "interp_masm_riscv.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "logging/log.hpp" +#include "oops/arrayOop.hpp" +#include "oops/markWord.hpp" +#include "oops/method.hpp" +#include "oops/methodData.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/powerOfTwo.hpp" + +void InterpreterMacroAssembler::narrow(Register result) { + // Get method->_constMethod->_result_type + ld(t0, Address(fp, frame::interpreter_frame_method_offset * wordSize)); + ld(t0, Address(t0, Method::const_offset())); + lbu(t0, Address(t0, ConstMethod::result_type_offset())); + + Label done, notBool, notByte, notChar; + + // common case first + mv(t1, T_INT); + beq(t0, t1, done); + + // mask integer result to narrower return type. + mv(t1, T_BOOLEAN); + bne(t0, t1, notBool); + + andi(result, result, 0x1); + j(done); + + bind(notBool); + mv(t1, T_BYTE); + bne(t0, t1, notByte); + sign_extend(result, result, 8); + j(done); + + bind(notByte); + mv(t1, T_CHAR); + bne(t0, t1, notChar); + zero_extend(result, result, 16); + j(done); + + bind(notChar); + sign_extend(result, result, 16); + + // Nothing to do for T_INT + bind(done); + addw(result, result, zr); +} + +void InterpreterMacroAssembler::jump_to_entry(address entry) { + assert(entry != NULL, "Entry must have been generated by now"); + j(entry); +} + +void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { + if (JvmtiExport::can_pop_frame()) { + Label L; + // Initiate popframe handling only if it is not already being + // processed. If the flag has the popframe_processing bit set, + // it means that this code is called *during* popframe handling - we + // don't want to reenter. + // This method is only called just after the call into the vm in + // call_VM_base, so the arg registers are available. + lwu(t1, Address(xthread, JavaThread::popframe_condition_offset())); + andi(t0, t1, JavaThread::popframe_pending_bit); + beqz(t0, L); + andi(t0, t1, JavaThread::popframe_processing_bit); + bnez(t0, L); + // Call Interpreter::remove_activation_preserving_args_entry() to get the + // address of the same-named entrypoint in the generated interpreter code. + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); + jr(x10); + bind(L); + } +} + + +void InterpreterMacroAssembler::load_earlyret_value(TosState state) { + ld(x12, Address(xthread, JavaThread::jvmti_thread_state_offset())); + const Address tos_addr(x12, JvmtiThreadState::earlyret_tos_offset()); + const Address oop_addr(x12, JvmtiThreadState::earlyret_oop_offset()); + const Address val_addr(x12, JvmtiThreadState::earlyret_value_offset()); + switch (state) { + case atos: + ld(x10, oop_addr); + sd(zr, oop_addr); + verify_oop(x10); + break; + case ltos: + ld(x10, val_addr); + break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: + lwu(x10, val_addr); + break; + case ftos: + flw(f10, val_addr); + break; + case dtos: + fld(f10, val_addr); + break; + case vtos: + /* nothing to do */ + break; + default: + ShouldNotReachHere(); + } + // Clean up tos value in the thread object + mvw(t0, (int) ilgl); + sw(t0, tos_addr); + sw(zr, val_addr); +} + + +void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { + if (JvmtiExport::can_force_early_return()) { + Label L; + ld(t0, Address(xthread, JavaThread::jvmti_thread_state_offset())); + beqz(t0, L); // if [thread->jvmti_thread_state() == NULL] then exit + + // Initiate earlyret handling only if it is not already being processed. + // If the flag has the earlyret_processing bit set, it means that this code + // is called *during* earlyret handling - we don't want to reenter. + lwu(t0, Address(t0, JvmtiThreadState::earlyret_state_offset())); + mv(t1, JvmtiThreadState::earlyret_pending); + bne(t0, t1, L); + + // Call Interpreter::remove_activation_early_entry() to get the address of the + // same-named entrypoint in the generated interpreter code. + ld(t0, Address(xthread, JavaThread::jvmti_thread_state_offset())); + lwu(t0, Address(t0, JvmtiThreadState::earlyret_tos_offset())); + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), t0); + jr(x10); + bind(L); + } +} + +void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { + assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); + lhu(reg, Address(xbcp, bcp_offset)); + revb_h(reg, reg); +} + +void InterpreterMacroAssembler::get_dispatch() { + int32_t offset = 0; + la_patchable(xdispatch, ExternalAddress((address)Interpreter::dispatch_table()), offset); + addi(xdispatch, xdispatch, offset); +} + +void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index, + int bcp_offset, + size_t index_size) { + assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + if (index_size == sizeof(u2)) { + load_unsigned_short(index, Address(xbcp, bcp_offset)); + } else if (index_size == sizeof(u4)) { + lwu(index, Address(xbcp, bcp_offset)); + // Check if the secondary index definition is still ~x, otherwise + // we have to change the following assembler code to calculate the + // plain index. + assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); + xori(index, index, -1); + addw(index, index, zr); + } else if (index_size == sizeof(u1)) { + load_unsigned_byte(index, Address(xbcp, bcp_offset)); + } else { + ShouldNotReachHere(); + } +} + +// Return +// Rindex: index into constant pool +// Rcache: address of cache entry - ConstantPoolCache::base_offset() +// +// A caller must add ConstantPoolCache::base_offset() to Rcache to get +// the true address of the cache entry. +// +void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, + Register index, + int bcp_offset, + size_t index_size) { + assert_different_registers(cache, index); + assert_different_registers(cache, xcpool); + get_cache_index_at_bcp(index, bcp_offset, index_size); + assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); + // Convert from field index to ConstantPoolCacheEntry + // riscv already has the cache in xcpool so there is no need to + // install it in cache. Instead we pre-add the indexed offset to + // xcpool and return it in cache. All clients of this method need to + // be modified accordingly. + shadd(cache, index, xcpool, cache, 5); +} + + +void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache, + Register index, + Register bytecode, + int byte_no, + int bcp_offset, + size_t index_size) { + get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size); + // We use a 32-bit load here since the layout of 64-bit words on + // little-endian machines allow us that. + // n.b. unlike x86 cache already includes the index offset + la(bytecode, Address(cache, + ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::indices_offset())); + membar(MacroAssembler::AnyAny); + lwu(bytecode, bytecode); + membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + const int shift_count = (1 + byte_no) * BitsPerByte; + slli(bytecode, bytecode, XLEN - (shift_count + BitsPerByte)); + srli(bytecode, bytecode, XLEN - BitsPerByte); +} + +void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, + Register tmp, + int bcp_offset, + size_t index_size) { + assert(cache != tmp, "must use different register"); + get_cache_index_at_bcp(tmp, bcp_offset, index_size); + assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); + // Convert from field index to ConstantPoolCacheEntry index + // and from word offset to byte offset + assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, + "else change next line"); + ld(cache, Address(fp, frame::interpreter_frame_cache_offset * wordSize)); + // skip past the header + add(cache, cache, in_bytes(ConstantPoolCache::base_offset())); + // construct pointer to cache entry + shadd(cache, tmp, cache, tmp, 2 + LogBytesPerWord); +} + +// Load object from cpool->resolved_references(index) +void InterpreterMacroAssembler::load_resolved_reference_at_index( + Register result, Register index, Register tmp) { + assert_different_registers(result, index); + + get_constant_pool(result); + // Load pointer for resolved_references[] objArray + ld(result, Address(result, ConstantPool::cache_offset_in_bytes())); + ld(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); + resolve_oop_handle(result, tmp); + // Add in the index + addi(index, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT) >> LogBytesPerHeapOop); + shadd(result, index, result, index, LogBytesPerHeapOop); + load_heap_oop(result, Address(result, 0)); +} + +void InterpreterMacroAssembler::load_resolved_klass_at_offset( + Register cpool, Register index, Register klass, Register temp) { + shadd(temp, index, cpool, temp, LogBytesPerWord); + lhu(temp, Address(temp, sizeof(ConstantPool))); // temp = resolved_klass_index + ld(klass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // klass = cpool->_resolved_klasses + shadd(klass, temp, klass, temp, LogBytesPerWord); + ld(klass, Address(klass, Array::base_offset_in_bytes())); +} + +void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no, + Register method, + Register cache) { + const int method_offset = in_bytes( + ConstantPoolCache::base_offset() + + ((byte_no == TemplateTable::f2_byte) + ? ConstantPoolCacheEntry::f2_offset() + : ConstantPoolCacheEntry::f1_offset())); + + ld(method, Address(cache, method_offset)); // get f1 Method* +} + +// Generate a subtype check: branch to ok_is_subtype if sub_klass is a +// subtype of super_klass. +// +// Args: +// x10: superklass +// Rsub_klass: subklass +// +// Kills: +// x12, x15 +void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, + Label& ok_is_subtype) { + assert(Rsub_klass != x10, "x10 holds superklass"); + assert(Rsub_klass != x12, "x12 holds 2ndary super array length"); + assert(Rsub_klass != x15, "x15 holds 2ndary super array scan ptr"); + + // Profile the not-null value's klass. + profile_typecheck(x12, Rsub_klass, x15); // blows x12, reloads x15 + + // Do the check. + check_klass_subtype(Rsub_klass, x10, x12, ok_is_subtype); // blows x12 + + // Profile the failure of the check. + profile_typecheck_failed(x12); // blows x12 +} + +// Java Expression Stack + +void InterpreterMacroAssembler::pop_ptr(Register r) { + ld(r, Address(esp, 0)); + addi(esp, esp, wordSize); +} + +void InterpreterMacroAssembler::pop_i(Register r) { + lw(r, Address(esp, 0)); // lw do signed extended + addi(esp, esp, wordSize); +} + +void InterpreterMacroAssembler::pop_l(Register r) { + ld(r, Address(esp, 0)); + addi(esp, esp, 2 * Interpreter::stackElementSize); +} + +void InterpreterMacroAssembler::push_ptr(Register r) { + addi(esp, esp, -wordSize); + sd(r, Address(esp, 0)); +} + +void InterpreterMacroAssembler::push_i(Register r) { + addi(esp, esp, -wordSize); + addw(r, r, zr); // signed extended + sd(r, Address(esp, 0)); +} + +void InterpreterMacroAssembler::push_l(Register r) { + addi(esp, esp, -2 * wordSize); + sd(zr, Address(esp, wordSize)); + sd(r, Address(esp)); +} + +void InterpreterMacroAssembler::pop_f(FloatRegister r) { + flw(r, esp, 0); + addi(esp, esp, wordSize); +} + +void InterpreterMacroAssembler::pop_d(FloatRegister r) { + fld(r, esp, 0); + addi(esp, esp, 2 * Interpreter::stackElementSize); +} + +void InterpreterMacroAssembler::push_f(FloatRegister r) { + addi(esp, esp, -wordSize); + fsw(r, Address(esp, 0)); +} + +void InterpreterMacroAssembler::push_d(FloatRegister r) { + addi(esp, esp, -2 * wordSize); + fsd(r, Address(esp, 0)); +} + +void InterpreterMacroAssembler::pop(TosState state) { + switch (state) { + case atos: + pop_ptr(); + verify_oop(x10); + break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: + pop_i(); + break; + case ltos: + pop_l(); + break; + case ftos: + pop_f(); + break; + case dtos: + pop_d(); + break; + case vtos: + /* nothing to do */ + break; + default: + ShouldNotReachHere(); + } +} + +void InterpreterMacroAssembler::push(TosState state) { + switch (state) { + case atos: + verify_oop(x10); + push_ptr(); + break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: + push_i(); + break; + case ltos: + push_l(); + break; + case ftos: + push_f(); + break; + case dtos: + push_d(); + break; + case vtos: + /* nothing to do */ + break; + default: + ShouldNotReachHere(); + } +} + +// Helpers for swap and dup +void InterpreterMacroAssembler::load_ptr(int n, Register val) { + ld(val, Address(esp, Interpreter::expr_offset_in_bytes(n))); +} + +void InterpreterMacroAssembler::store_ptr(int n, Register val) { + sd(val, Address(esp, Interpreter::expr_offset_in_bytes(n))); +} + +void InterpreterMacroAssembler::load_float(Address src) { + flw(f10, src); +} + +void InterpreterMacroAssembler::load_double(Address src) { + fld(f10, src); +} + +void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { + // set sender sp + mv(x30, sp); + // record last_sp + sd(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); +} + +// Jump to from_interpreted entry of a call unless single stepping is possible +// in this thread in which case we must call the i2i entry +void InterpreterMacroAssembler::jump_from_interpreted(Register method) { + prepare_to_jump_from_interpreted(); + if (JvmtiExport::can_post_interpreter_events()) { + Label run_compiled_code; + // JVMTI events, such as single-stepping, are implemented partly by avoiding running + // compiled code in threads for which the event is enabled. Check here for + // interp_only_mode if these events CAN be enabled. + lwu(t0, Address(xthread, JavaThread::interp_only_mode_offset())); + beqz(t0, run_compiled_code); + ld(t0, Address(method, Method::interpreter_entry_offset())); + jr(t0); + bind(run_compiled_code); + } + + ld(t0, Address(method, Method::from_interpreted_offset())); + jr(t0); +} + +// The following two routines provide a hook so that an implementation +// can schedule the dispatch in two parts. amd64 does not do this. +void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { +} + +void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { + dispatch_next(state, step); +} + +void InterpreterMacroAssembler::dispatch_base(TosState state, + address* table, + bool verifyoop, + bool generate_poll, + Register Rs) { + // Pay attention to the argument Rs, which is acquiesce in t0. + if (VerifyActivationFrameSize) { + Unimplemented(); + } + if (verifyoop && state == atos) { + verify_oop(x10); + } + + Label safepoint; + address* const safepoint_table = Interpreter::safept_table(state); + bool needs_thread_local_poll = generate_poll && table != safepoint_table; + + if (needs_thread_local_poll) { + NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); + ld(t1, Address(xthread, JavaThread::polling_word_offset())); + andi(t1, t1, SafepointMechanism::poll_bit()); + bnez(t1, safepoint); + } + if (table == Interpreter::dispatch_table(state)) { + li(t1, Interpreter::distance_from_dispatch_table(state)); + add(t1, Rs, t1); + shadd(t1, t1, xdispatch, t1, 3); + } else { + mv(t1, (address)table); + shadd(t1, Rs, t1, Rs, 3); + } + ld(t1, Address(t1)); + jr(t1); + + if (needs_thread_local_poll) { + bind(safepoint); + la(t1, ExternalAddress((address)safepoint_table)); + shadd(t1, Rs, t1, Rs, 3); + ld(t1, Address(t1)); + jr(t1); + } +} + +void InterpreterMacroAssembler::dispatch_only(TosState state, bool generate_poll, Register Rs) { + dispatch_base(state, Interpreter::dispatch_table(state), true, generate_poll, Rs); +} + +void InterpreterMacroAssembler::dispatch_only_normal(TosState state, Register Rs) { + dispatch_base(state, Interpreter::normal_table(state), Rs); +} + +void InterpreterMacroAssembler::dispatch_only_noverify(TosState state, Register Rs) { + dispatch_base(state, Interpreter::normal_table(state), false, Rs); +} + +void InterpreterMacroAssembler::dispatch_next(TosState state, int step, bool generate_poll) { + // load next bytecode + load_unsigned_byte(t0, Address(xbcp, step)); + add(xbcp, xbcp, step); + dispatch_base(state, Interpreter::dispatch_table(state), true, generate_poll); +} + +void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { + // load current bytecode + lbu(t0, Address(xbcp, 0)); + dispatch_base(state, table); +} + +// remove activation +// +// Apply stack watermark barrier. +// Unlock the receiver if this is a synchronized method. +// Unlock any Java monitors from syncronized blocks. +// Remove the activation from the stack. +// +// If there are locked Java monitors +// If throw_monitor_exception +// throws IllegalMonitorStateException +// Else if install_monitor_exception +// installs IllegalMonitorStateException +// Else +// no error processing +void InterpreterMacroAssembler::remove_activation( + TosState state, + bool throw_monitor_exception, + bool install_monitor_exception, + bool notify_jvmdi) { + // Note: Registers x13 may be in use for the + // result check if synchronized method + Label unlocked, unlock, no_unlock; + + // The below poll is for the stack watermark barrier. It allows fixing up frames lazily, + // that would normally not be safe to use. Such bad returns into unsafe territory of + // the stack, will call InterpreterRuntime::at_unwind. + Label slow_path; + Label fast_path; + safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + j(fast_path); + + bind(slow_path); + push(state); + set_last_Java_frame(esp, fp, (address)pc(), t0); + super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), xthread); + reset_last_Java_frame(true); + pop(state); + + bind(fast_path); + + // get the value of _do_not_unlock_if_synchronized into x13 + const Address do_not_unlock_if_synchronized(xthread, + in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); + lbu(x13, do_not_unlock_if_synchronized); + sb(zr, do_not_unlock_if_synchronized); // reset the flag + + // get method access flags + ld(x11, Address(fp, frame::interpreter_frame_method_offset * wordSize)); + ld(x12, Address(x11, Method::access_flags_offset())); + andi(t0, x12, JVM_ACC_SYNCHRONIZED); + beqz(t0, unlocked); + + // Don't unlock anything if the _do_not_unlock_if_synchronized flag + // is set. + bnez(x13, no_unlock); + + // unlock monitor + push(state); // save result + + // BasicObjectLock will be first in list, since this is a + // synchronized method. However, need to check that the object has + // not been unlocked by an explicit monitorexit bytecode. + const Address monitor(fp, frame::interpreter_frame_initial_sp_offset * + wordSize - (int) sizeof(BasicObjectLock)); + // We use c_rarg1 so that if we go slow path it will be the correct + // register for unlock_object to pass to VM directly + la(c_rarg1, monitor); // address of first monitor + + ld(x10, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); + bnez(x10, unlock); + + pop(state); + if (throw_monitor_exception) { + // Entry already unlocked, need to throw exception + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_illegal_monitor_state_exception)); + should_not_reach_here(); + } else { + // Monitor already unlocked during a stack unroll. If requested, + // install an illegal_monitor_state_exception. Continue with + // stack unrolling. + if (install_monitor_exception) { + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::new_illegal_monitor_state_exception)); + } + j(unlocked); + } + + bind(unlock); + unlock_object(c_rarg1); + pop(state); + + // Check that for block-structured locking (i.e., that all locked + // objects has been unlocked) + bind(unlocked); + + // x10: Might contain return value + + // Check that all monitors are unlocked + { + Label loop, exception, entry, restart; + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + const Address monitor_block_top( + fp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const Address monitor_block_bot( + fp, frame::interpreter_frame_initial_sp_offset * wordSize); + + bind(restart); + // We use c_rarg1 so that if we go slow path it will be the correct + // register for unlock_object to pass to VM directly + ld(c_rarg1, monitor_block_top); // points to current entry, starting + // with top-most entry + la(x9, monitor_block_bot); // points to word before bottom of + // monitor block + + j(entry); + + // Entry already locked, need to throw exception + bind(exception); + + if (throw_monitor_exception) { + // Throw exception + MacroAssembler::call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime:: + throw_illegal_monitor_state_exception)); + + should_not_reach_here(); + } else { + // Stack unrolling. Unlock object and install illegal_monitor_exception. + // Unlock does not block, so don't have to worry about the frame. + // We don't have to preserve c_rarg1 since we are going to throw an exception. + + push(state); + unlock_object(c_rarg1); + pop(state); + + if (install_monitor_exception) { + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime:: + new_illegal_monitor_state_exception)); + } + + j(restart); + } + + bind(loop); + // check if current entry is used + add(t0, c_rarg1, BasicObjectLock::obj_offset_in_bytes()); + ld(t0, Address(t0, 0)); + bnez(t0, exception); + + add(c_rarg1, c_rarg1, entry_size); // otherwise advance to next entry + bind(entry); + bne(c_rarg1, x9, loop); // check if bottom reached if not at bottom then check this entry + } + + bind(no_unlock); + + // jvmti support + if (notify_jvmdi) { + notify_method_exit(state, NotifyJVMTI); // preserve TOSCA + + } else { + notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA + } + + // remove activation + // get sender esp + ld(t1, + Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); + if (StackReservedPages > 0) { + // testing if reserved zone needs to be re-enabled + Label no_reserved_zone_enabling; + + ld(t0, Address(xthread, JavaThread::reserved_stack_activation_offset())); + ble(t1, t0, no_reserved_zone_enabling); + + call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), xthread); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_delayed_StackOverflowError)); + should_not_reach_here(); + + bind(no_reserved_zone_enabling); + } + + // restore sender esp + mv(esp, t1); + + // remove frame anchor + leave(); + // If we're returning to interpreted code we will shortly be + // adjusting SP to allow some space for ESP. If we're returning to + // compiled code the saved sender SP was saved in sender_sp, so this + // restores it. + andi(sp, esp, -16); +} + +// Lock object +// +// Args: +// c_rarg1: BasicObjectLock to be used for locking +// +// Kills: +// x10 +// c_rarg0, c_rarg1, c_rarg2, c_rarg3, .. (param regs) +// t0, t1 (temp regs) +void InterpreterMacroAssembler::lock_object(Register lock_reg) +{ + assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1"); + if (UseHeavyMonitors) { + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), + lock_reg); + } else { + Label done; + + const Register swap_reg = x10; + const Register tmp = c_rarg2; + const Register obj_reg = c_rarg3; // Will contain the oop + + const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); + const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); + const int mark_offset = lock_offset + + BasicLock::displaced_header_offset_in_bytes(); + + Label slow_case; + + // Load object pointer into obj_reg c_rarg3 + ld(obj_reg, Address(lock_reg, obj_offset)); + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, obj_reg); + lwu(tmp, Address(tmp, Klass::access_flags_offset())); + andi(tmp, tmp, JVM_ACC_IS_VALUE_BASED_CLASS); + bnez(tmp, slow_case); + } + + // Load (object->mark() | 1) into swap_reg + ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + ori(swap_reg, t0, 1); + + // Save (object->mark() | 1) into BasicLock's displaced header + sd(swap_reg, Address(lock_reg, mark_offset)); + + assert(lock_offset == 0, + "displached header must be first word in BasicObjectLock"); + + cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, done, /*fallthrough*/NULL); + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 7) == 0, and + // 2) sp <= mark < mark + os::pagesize() + // + // These 3 tests can be done by evaluating the following + // expression: ((mark - sp) & (7 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 3 bits clear. + // NOTE: the oopMark is in swap_reg x10 as the result of cmpxchg + sub(swap_reg, swap_reg, sp); + li(t0, (int64_t)(7 - os::vm_page_size())); + andr(swap_reg, swap_reg, t0); + + // Save the test result, for recursive case, the result is zero + sd(swap_reg, Address(lock_reg, mark_offset)); + beqz(swap_reg, done); + + bind(slow_case); + + // Call the runtime routine for slow case + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), + lock_reg); + + bind(done); + } +} + + +// Unlocks an object. Used in monitorexit bytecode and +// remove_activation. Throws an IllegalMonitorException if object is +// not locked by current thread. +// +// Args: +// c_rarg1: BasicObjectLock for lock +// +// Kills: +// x10 +// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ... (param regs) +// t0, t1 (temp regs) +void InterpreterMacroAssembler::unlock_object(Register lock_reg) +{ + assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1"); + + if (UseHeavyMonitors) { + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); + } else { + Label done; + + const Register swap_reg = x10; + const Register header_reg = c_rarg2; // Will contain the old oopMark + const Register obj_reg = c_rarg3; // Will contain the oop + + save_bcp(); // Save in case of exception + + // Convert from BasicObjectLock structure to object and BasicLock + // structure Store the BasicLock address into x10 + la(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); + + // Load oop into obj_reg(c_rarg3) + ld(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); + + // Free entry + sd(zr, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); + + // Load the old header from BasicLock structure + ld(header_reg, Address(swap_reg, + BasicLock::displaced_header_offset_in_bytes())); + + // Test for recursion + beqz(header_reg, done); + + // Atomic swap back the old header + cmpxchg_obj_header(swap_reg, header_reg, obj_reg, t0, done, /*fallthrough*/NULL); + + // Call the runtime routine for slow case. + sd(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // restore obj + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); + + bind(done); + + restore_bcp(); + } +} + + +void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, + Label& zero_continue) { + assert(ProfileInterpreter, "must be profiling interpreter"); + ld(mdp, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); + beqz(mdp, zero_continue); +} + +// Set the method data pointer for the current bcp. +void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { + assert(ProfileInterpreter, "must be profiling interpreter"); + Label set_mdp; + push_reg(0xc00, sp); // save x10, x11 + + // Test MDO to avoid the call if it is NULL. + ld(x10, Address(xmethod, in_bytes(Method::method_data_offset()))); + beqz(x10, set_mdp); + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), xmethod, xbcp); + // x10: mdi + // mdo is guaranteed to be non-zero here, we checked for it before the call. + ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); + la(x11, Address(x11, in_bytes(MethodData::data_offset()))); + add(x10, x11, x10); + sd(x10, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); + bind(set_mdp); + pop_reg(0xc00, sp); +} + +void InterpreterMacroAssembler::verify_method_data_pointer() { + assert(ProfileInterpreter, "must be profiling interpreter"); +#ifdef ASSERT + Label verify_continue; + add(sp, sp, -4 * wordSize); + sd(x10, Address(sp, 0)); + sd(x11, Address(sp, wordSize)); + sd(x12, Address(sp, 2 * wordSize)); + sd(x13, Address(sp, 3 * wordSize)); + test_method_data_pointer(x13, verify_continue); // If mdp is zero, continue + get_method(x11); + + // If the mdp is valid, it will point to a DataLayout header which is + // consistent with the bcp. The converse is highly probable also. + lh(x12, Address(x13, in_bytes(DataLayout::bci_offset()))); + ld(t0, Address(x11, Method::const_offset())); + add(x12, x12, t0); + la(x12, Address(x12, ConstMethod::codes_offset())); + beq(x12, xbcp, verify_continue); + // x10: method + // xbcp: bcp // xbcp == 22 + // x13: mdp + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), + x11, xbcp, x13); + bind(verify_continue); + ld(x10, Address(sp, 0)); + ld(x11, Address(sp, wordSize)); + ld(x12, Address(sp, 2 * wordSize)); + ld(x13, Address(sp, 3 * wordSize)); + add(sp, sp, 4 * wordSize); +#endif // ASSERT +} + + +void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, + int constant, + Register value) { + assert(ProfileInterpreter, "must be profiling interpreter"); + Address data(mdp_in, constant); + sd(value, data); +} + + +void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, + int constant, + bool decrement) { + increment_mdp_data_at(mdp_in, noreg, constant, decrement); +} + +void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, + Register reg, + int constant, + bool decrement) { + assert(ProfileInterpreter, "must be profiling interpreter"); + // %%% this does 64bit counters at best it is wasting space + // at worst it is a rare bug when counters overflow + + assert_different_registers(t1, t0, mdp_in, reg); + + Address addr1(mdp_in, constant); + Address addr2(t1, 0); + Address &addr = addr1; + if (reg != noreg) { + la(t1, addr1); + add(t1, t1, reg); + addr = addr2; + } + + if (decrement) { + ld(t0, addr); + addi(t0, t0, -DataLayout::counter_increment); + Label L; + bltz(t0, L); // skip store if counter underflow + sd(t0, addr); + bind(L); + } else { + assert(DataLayout::counter_increment == 1, + "flow-free idiom only works with 1"); + ld(t0, addr); + addi(t0, t0, DataLayout::counter_increment); + Label L; + blez(t0, L); // skip store if counter overflow + sd(t0, addr); + bind(L); + } +} + +void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, + int flag_byte_constant) { + assert(ProfileInterpreter, "must be profiling interpreter"); + int flags_offset = in_bytes(DataLayout::flags_offset()); + // Set the flag + lbu(t1, Address(mdp_in, flags_offset)); + ori(t1, t1, flag_byte_constant); + sb(t1, Address(mdp_in, flags_offset)); +} + + +void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, + int offset, + Register value, + Register test_value_out, + Label& not_equal_continue) { + assert(ProfileInterpreter, "must be profiling interpreter"); + if (test_value_out == noreg) { + ld(t1, Address(mdp_in, offset)); + bne(value, t1, not_equal_continue); + } else { + // Put the test value into a register, so caller can use it: + ld(test_value_out, Address(mdp_in, offset)); + bne(value, test_value_out, not_equal_continue); + } +} + + +void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, + int offset_of_disp) { + assert(ProfileInterpreter, "must be profiling interpreter"); + ld(t1, Address(mdp_in, offset_of_disp)); + add(mdp_in, mdp_in, t1); + sd(mdp_in, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); +} + +void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, + Register reg, + int offset_of_disp) { + assert(ProfileInterpreter, "must be profiling interpreter"); + add(t1, mdp_in, reg); + ld(t1, Address(t1, offset_of_disp)); + add(mdp_in, mdp_in, t1); + sd(mdp_in, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); +} + + +void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, + int constant) { + assert(ProfileInterpreter, "must be profiling interpreter"); + addi(mdp_in, mdp_in, (unsigned)constant); + sd(mdp_in, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); +} + + +void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { + assert(ProfileInterpreter, "must be profiling interpreter"); + + // save/restore across call_VM + addi(sp, sp, -2 * wordSize); + sd(zr, Address(sp, 0)); + sd(return_bci, Address(sp, wordSize)); + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), + return_bci); + ld(zr, Address(sp, 0)); + ld(return_bci, Address(sp, wordSize)); + addi(sp, sp, 2 * wordSize); +} + +void InterpreterMacroAssembler::profile_taken_branch(Register mdp, + Register bumped_count) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + // Otherwise, assign to mdp + test_method_data_pointer(mdp, profile_continue); + + // We are taking a branch. Increment the taken count. + Address data(mdp, in_bytes(JumpData::taken_offset())); + ld(bumped_count, data); + assert(DataLayout::counter_increment == 1, + "flow-free idiom only works with 1"); + addi(bumped_count, bumped_count, DataLayout::counter_increment); + Label L; + // eg: bumped_count=0x7fff ffff ffff ffff + 1 < 0. so we use <= 0; + blez(bumped_count, L); // skip store if counter overflow, + sd(bumped_count, data); + bind(L); + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are taking a branch. Increment the not taken count. + increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); + + // The method data pointer needs to be updated to correspond to + // the next bytecode + update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_call(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are making a call. Increment the count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_final_call(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are making a call. Increment the count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_constant(mdp, + in_bytes(VirtualCallData:: + virtual_call_data_size())); + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_virtual_call(Register receiver, + Register mdp, + Register reg2, + bool receiver_can_be_null) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + Label skip_receiver_profile; + if (receiver_can_be_null) { + Label not_null; + // We are making a call. Increment the count for null receiver. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + j(skip_receiver_profile); + bind(not_null); + } + + // Record the receiver type. + record_klass_in_profile(receiver, mdp, reg2, true); + bind(skip_receiver_profile); + + // The method data pointer needs to be updated to reflect the new target. + + update_mdp_by_constant(mdp, + in_bytes(VirtualCallData:: + virtual_call_data_size())); + bind(profile_continue); + } +} + +// This routine creates a state machine for updating the multi-row +// type profile at a virtual call site (or other type-sensitive bytecode). +// The machine visits each row (of receiver/count) until the receiver type +// is found, or until it runs out of rows. At the same time, it remembers +// the location of the first empty row. (An empty row records null for its +// receiver, and can be allocated for a newly-observed receiver type.) +// Because there are two degrees of freedom in the state, a simple linear +// search will not work; it must be a decision tree. Hence this helper +// function is recursive, to generate the required tree structured code. +// It's the interpreter, so we are trading off code space for speed. +// See below for example code. +void InterpreterMacroAssembler::record_klass_in_profile_helper( + Register receiver, Register mdp, + Register reg2, + Label& done, bool is_virtual_call) { + if (TypeProfileWidth == 0) { + if (is_virtual_call) { + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + } + + } else { + int non_profiled_offset = -1; + if (is_virtual_call) { + non_profiled_offset = in_bytes(CounterData::count_offset()); + } + + record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth, + &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset); + } +} + +void InterpreterMacroAssembler::record_item_in_profile_helper( + Register item, Register mdp, Register reg2, int start_row, Label& done, int total_rows, + OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, int non_profiled_offset) { + int last_row = total_rows - 1; + assert(start_row <= last_row, "must be work left to do"); + // Test this row for both the item and for null. + // Take any of three different outcomes: + // 1. found item => increment count and goto done + // 2. found null => keep looking for case 1, maybe allocate this cell + // 3. found something else => keep looking for cases 1 and 2 + // Case 3 is handled by a recursive call. + for (int row = start_row; row <= last_row; row++) { + Label next_test; + bool test_for_null_also = (row == start_row); + + // See if the item is item[n]. + int item_offset = in_bytes(item_offset_fn(row)); + test_mdp_data_at(mdp, item_offset, item, + (test_for_null_also ? reg2 : noreg), + next_test); + // (Reg2 now contains the item from the CallData.) + + // The item is item[n]. Increment count[n]. + int count_offset = in_bytes(item_count_offset_fn(row)); + increment_mdp_data_at(mdp, count_offset); + j(done); + bind(next_test); + + if (test_for_null_also) { + Label found_null; + // Failed the equality check on item[n]... Test for null. + if (start_row == last_row) { + // The only thing left to do is handle the null case. + if (non_profiled_offset >= 0) { + beqz(reg2, found_null); + // Item did not match any saved item and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + increment_mdp_data_at(mdp, non_profiled_offset); + j(done); + bind(found_null); + } else { + bnez(reg2, done); + } + break; + } + // Since null is rare, make it be the branch-taken case. + beqz(reg2, found_null); + + // Put all the "Case 3" tests here. + record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows, + item_offset_fn, item_count_offset_fn, non_profiled_offset); + + // Found a null. Keep searching for a matching item, + // but remember that this is an empty (unused) slot. + bind(found_null); + } + } + + // In the fall-through case, we found no matching item, but we + // observed the item[start_row] is NULL. + // Fill in the item field and increment the count. + int item_offset = in_bytes(item_offset_fn(start_row)); + set_mdp_data_at(mdp, item_offset, item); + int count_offset = in_bytes(item_count_offset_fn(start_row)); + mv(reg2, DataLayout::counter_increment); + set_mdp_data_at(mdp, count_offset, reg2); + if (start_row > 0) { + j(done); + } +} + +// Example state machine code for three profile rows: +// # main copy of decision tree, rooted at row[1] +// if (row[0].rec == rec) then [ +// row[0].incr() +// goto done +// ] +// if (row[0].rec != NULL) then [ +// # inner copy of decision tree, rooted at row[1] +// if (row[1].rec == rec) then [ +// row[1].incr() +// goto done +// ] +// if (row[1].rec != NULL) then [ +// # degenerate decision tree, rooted at row[2] +// if (row[2].rec == rec) then [ +// row[2].incr() +// goto done +// ] +// if (row[2].rec != NULL) then [ +// count.incr() +// goto done +// ] # overflow +// row[2].init(rec) +// goto done +// ] else [ +// # remember row[1] is empty +// if (row[2].rec == rec) then [ +// row[2].incr() +// goto done +// ] +// row[1].init(rec) +// goto done +// ] +// else [ +// # remember row[0] is empty +// if (row[1].rec == rec) then [ +// row[1].incr() +// goto done +// ] +// if (row[2].rec == rec) then [ +// row[2].incr() +// goto done +// ] +// row[0].init(rec) +// goto done +// ] +// done: + +void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, + Register mdp, Register reg2, + bool is_virtual_call) { + assert(ProfileInterpreter, "must be profiling"); + Label done; + + record_klass_in_profile_helper(receiver, mdp, reg2, done, is_virtual_call); + + bind(done); +} + +void InterpreterMacroAssembler::profile_ret(Register return_bci, Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Update the total ret count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + for (uint row = 0; row < RetData::row_limit(); row++) { + Label next_test; + + // See if return_bci is equal to bci[n]: + test_mdp_data_at(mdp, + in_bytes(RetData::bci_offset(row)), + return_bci, noreg, + next_test); + + // return_bci is equal to bci[n]. Increment the count. + increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_offset(mdp, + in_bytes(RetData::bci_displacement_offset(row))); + j(profile_continue); + bind(next_test); + } + + update_mdp_for_ret(return_bci); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_null_seen(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); + + // The method data pointer needs to be updated. + int mdp_delta = in_bytes(BitData::bit_data_size()); + if (TypeProfileCasts) { + mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + } + update_mdp_by_constant(mdp, mdp_delta); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { + if (ProfileInterpreter && TypeProfileCasts) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + int count_offset = in_bytes(CounterData::count_offset()); + // Back up the address, since we have already bumped the mdp. + count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); + + // *Decrement* the counter. We expect to see zero or small negatives. + increment_mdp_data_at(mdp, count_offset, true); + + bind (profile_continue); + } +} + +void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // The method data pointer needs to be updated. + int mdp_delta = in_bytes(BitData::bit_data_size()); + if (TypeProfileCasts) { + mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + + // Record the object type. + record_klass_in_profile(klass, mdp, reg2, false); + } + update_mdp_by_constant(mdp, mdp_delta); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_switch_default(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Update the default case count + increment_mdp_data_at(mdp, + in_bytes(MultiBranchData::default_count_offset())); + + // The method data pointer needs to be updated. + update_mdp_by_offset(mdp, + in_bytes(MultiBranchData:: + default_displacement_offset())); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_switch_case(Register index, + Register mdp, + Register reg2) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Build the base (index * per_case_size_in_bytes()) + + // case_array_offset_in_bytes() + mvw(reg2, in_bytes(MultiBranchData::per_case_size())); + mvw(t0, in_bytes(MultiBranchData::case_array_offset())); + Assembler::mul(index, index, reg2); + Assembler::add(index, index, t0); + + // Update the case count + increment_mdp_data_at(mdp, + index, + in_bytes(MultiBranchData::relative_count_offset())); + + // The method data pointer need to be updated. + update_mdp_by_offset(mdp, + index, + in_bytes(MultiBranchData:: + relative_displacement_offset())); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { ; } + +void InterpreterMacroAssembler::notify_method_entry() { + // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to + // track stack depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + if (JvmtiExport::can_post_interpreter_events()) { + Label L; + lwu(x13, Address(xthread, JavaThread::interp_only_mode_offset())); + beqz(x13, L); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_method_entry)); + bind(L); + } + + { + SkipIfEqual skip(this, &DTraceMethodProbes, false); + get_method(c_rarg1); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), + xthread, c_rarg1); + } + + // RedefineClasses() tracing support for obsolete method entry + if (log_is_enabled(Trace, redefine, class, obsolete)) { + get_method(c_rarg1); + call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), + xthread, c_rarg1); + } +} + + +void InterpreterMacroAssembler::notify_method_exit( + TosState state, NotifyMethodExitMode mode) { + // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to + // track stack depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { + Label L; + // Note: frame::interpreter_frame_result has a dependency on how the + // method result is saved across the call to post_method_exit. If this + // is changed then the interpreter_frame_result implementation will + // need to be updated too. + + // template interpreter will leave the result on the top of the stack. + push(state); + lwu(x13, Address(xthread, JavaThread::interp_only_mode_offset())); + beqz(x13, L); + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); + bind(L); + pop(state); + } + + { + SkipIfEqual skip(this, &DTraceMethodProbes, false); + push(state); + get_method(c_rarg1); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), + xthread, c_rarg1); + pop(state); + } +} + + +// Jump if ((*counter_addr += increment) & mask) satisfies the condition. +void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, + int increment, Address mask, + Register tmp1, Register tmp2, + bool preloaded, Label* where) { + Label done; + if (!preloaded) { + lwu(tmp1, counter_addr); + } + add(tmp1, tmp1, increment); + sw(tmp1, counter_addr); + lwu(tmp2, mask); + andr(tmp1, tmp1, tmp2); + bnez(tmp1, done); + j(*where); // offset is too large so we have to use j instead of beqz here + bind(done); +} + +void InterpreterMacroAssembler::call_VM_leaf_base(address entry_point, + int number_of_arguments) { + // interpreter specific + // + // Note: No need to save/restore rbcp & rlocals pointer since these + // are callee saved registers and no blocking/ GC can happen + // in leaf calls. +#ifdef ASSERT + { + Label L; + ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + beqz(t0, L); + stop("InterpreterMacroAssembler::call_VM_leaf_base:" + " last_sp != NULL"); + bind(L); + } +#endif /* ASSERT */ + // super call + MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); +} + +void InterpreterMacroAssembler::call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + // interpreter specific + // + // Note: Could avoid restoring locals ptr (callee saved) - however doesn't + // really make a difference for these runtime calls, since they are + // slow anyway. Btw., bcp must be saved/restored since it may change + // due to GC. + save_bcp(); +#ifdef ASSERT + { + Label L; + ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + beqz(t0, L); + stop("InterpreterMacroAssembler::call_VM_base:" + " last_sp != NULL"); + bind(L); + } +#endif /* ASSERT */ + // super call + MacroAssembler::call_VM_base(oop_result, noreg, last_java_sp, + entry_point, number_of_arguments, + check_exceptions); +// interpreter specific + restore_bcp(); + restore_locals(); +} + +void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr, Register tmp) { + assert_different_registers(obj, tmp, t0, mdo_addr.base()); + Label update, next, none; + + verify_oop(obj); + + bnez(obj, update); + orptr(mdo_addr, TypeEntries::null_seen, t0, tmp); + j(next); + + bind(update); + load_klass(obj, obj); + + ld(t0, mdo_addr); + xorr(obj, obj, t0); + andi(t0, obj, TypeEntries::type_klass_mask); + beqz(t0, next); // klass seen before, nothing to + // do. The unknown bit may have been + // set already but no need to check. + + andi(t0, obj, TypeEntries::type_unknown); + bnez(t0, next); + // already unknown. Nothing to do anymore. + + ld(t0, mdo_addr); + beqz(t0, none); + li(tmp, (u1)TypeEntries::null_seen); + beq(t0, tmp, none); + // There is a chance that the checks above (re-reading profiling + // data from memory) fail if another thread has just set the + // profiling to this obj's klass + ld(t0, mdo_addr); + xorr(obj, obj, t0); + andi(t0, obj, TypeEntries::type_klass_mask); + beqz(t0, next); + + // different than before. Cannot keep accurate profile. + orptr(mdo_addr, TypeEntries::type_unknown, t0, tmp); + j(next); + + bind(none); + // first time here. Set profile type. + sd(obj, mdo_addr); + + bind(next); +} + +void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) { + if (!ProfileInterpreter) { + return; + } + + if (MethodData::profile_arguments() || MethodData::profile_return()) { + Label profile_continue; + + test_method_data_pointer(mdp, profile_continue); + + int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size()); + + lbu(t0, Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start)); + if (is_virtual) { + li(tmp, (u1)DataLayout::virtual_call_type_data_tag); + bne(t0, tmp, profile_continue); + } else { + li(tmp, (u1)DataLayout::call_type_data_tag); + bne(t0, tmp, profile_continue); + } + + // calculate slot step + static int stack_slot_offset0 = in_bytes(TypeEntriesAtCall::stack_slot_offset(0)); + static int slot_step = in_bytes(TypeEntriesAtCall::stack_slot_offset(1)) - stack_slot_offset0; + + // calculate type step + static int argument_type_offset0 = in_bytes(TypeEntriesAtCall::argument_type_offset(0)); + static int type_step = in_bytes(TypeEntriesAtCall::argument_type_offset(1)) - argument_type_offset0; + + if (MethodData::profile_arguments()) { + Label done, loop, loopEnd, profileArgument, profileReturnType; + RegSet pushed_registers; + pushed_registers += x15; + pushed_registers += x16; + pushed_registers += x17; + Register mdo_addr = x15; + Register index = x16; + Register off_to_args = x17; + push_reg(pushed_registers, sp); + + mv(off_to_args, in_bytes(TypeEntriesAtCall::args_data_offset())); + mv(t0, TypeProfileArgsLimit); + beqz(t0, loopEnd); + + mv(index, zr); // index < TypeProfileArgsLimit + bind(loop); + bgtz(index, profileReturnType); + li(t0, (int)MethodData::profile_return()); + beqz(t0, profileArgument); // (index > 0 || MethodData::profile_return()) == false + bind(profileReturnType); + // If return value type is profiled we may have no argument to profile + ld(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset()))); + mv(t1, - TypeStackSlotEntries::per_arg_count()); + mul(t1, index, t1); + add(tmp, tmp, t1); + li(t1, TypeStackSlotEntries::per_arg_count()); + add(t0, mdp, off_to_args); + blt(tmp, t1, done); + + bind(profileArgument); + + ld(tmp, Address(callee, Method::const_offset())); + load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset())); + // stack offset o (zero based) from the start of the argument + // list, for n arguments translates into offset n - o - 1 from + // the end of the argument list + li(t0, stack_slot_offset0); + li(t1, slot_step); + mul(t1, index, t1); + add(t0, t0, t1); + add(t0, mdp, t0); + ld(t0, Address(t0)); + sub(tmp, tmp, t0); + addi(tmp, tmp, -1); + Address arg_addr = argument_address(tmp); + ld(tmp, arg_addr); + + li(t0, argument_type_offset0); + li(t1, type_step); + mul(t1, index, t1); + add(t0, t0, t1); + add(mdo_addr, mdp, t0); + Address mdo_arg_addr(mdo_addr, 0); + profile_obj_type(tmp, mdo_arg_addr, t1); + + int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); + addi(off_to_args, off_to_args, to_add); + + // increment index by 1 + addi(index, index, 1); + li(t1, TypeProfileArgsLimit); + blt(index, t1, loop); + bind(loopEnd); + + if (MethodData::profile_return()) { + ld(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset()))); + addi(tmp, tmp, -TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count()); + } + + add(t0, mdp, off_to_args); + bind(done); + mv(mdp, t0); + + // unspill the clobbered registers + pop_reg(pushed_registers, sp); + + if (MethodData::profile_return()) { + // We're right after the type profile for the last + // argument. tmp is the number of cells left in the + // CallTypeData/VirtualCallTypeData to reach its end. Non null + // if there's a return to profile. + assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type"); + shadd(mdp, tmp, mdp, tmp, exact_log2(DataLayout::cell_size)); + } + sd(mdp, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); + } else { + assert(MethodData::profile_return(), "either profile call args or call ret"); + update_mdp_by_constant(mdp, in_bytes(TypeEntriesAtCall::return_only_size())); + } + + // mdp points right after the end of the + // CallTypeData/VirtualCallTypeData, right after the cells for the + // return value type if there's one + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) { + assert_different_registers(mdp, ret, tmp, xbcp, t0, t1); + if (ProfileInterpreter && MethodData::profile_return()) { + Label profile_continue, done; + + test_method_data_pointer(mdp, profile_continue); + + if (MethodData::profile_return_jsr292_only()) { + assert(Method::intrinsic_id_size_in_bytes() == 2, "assuming Method::_intrinsic_id is u2"); + + // If we don't profile all invoke bytecodes we must make sure + // it's a bytecode we indeed profile. We can't go back to the + // begining of the ProfileData we intend to update to check its + // type because we're right after it and we don't known its + // length + Label do_profile; + lbu(t0, Address(xbcp, 0)); + li(tmp, (u1)Bytecodes::_invokedynamic); + beq(t0, tmp, do_profile); + li(tmp, (u1)Bytecodes::_invokehandle); + beq(t0, tmp, do_profile); + get_method(tmp); + lhu(t0, Address(tmp, Method::intrinsic_id_offset_in_bytes())); + li(t1, static_cast(vmIntrinsics::_compiledLambdaForm)); + bne(t0, t1, profile_continue); + bind(do_profile); + } + + Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size())); + mv(tmp, ret); + profile_obj_type(tmp, mdo_ret_addr, t1); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2, Register tmp3) { + assert_different_registers(t0, t1, mdp, tmp1, tmp2, tmp3); + if (ProfileInterpreter && MethodData::profile_parameters()) { + Label profile_continue, done; + + test_method_data_pointer(mdp, profile_continue); + + // Load the offset of the area within the MDO used for + // parameters. If it's negative we're not profiling any parameters + lwu(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); + srli(tmp2, tmp1, 31); + bnez(tmp2, profile_continue); // i.e. sign bit set + + // Compute a pointer to the area for parameters from the offset + // and move the pointer to the slot for the last + // parameters. Collect profiling from last parameter down. + // mdo start + parameters offset + array length - 1 + add(mdp, mdp, tmp1); + ld(tmp1, Address(mdp, ArrayData::array_len_offset())); + add(tmp1, tmp1, - TypeStackSlotEntries::per_arg_count()); + + Label loop; + bind(loop); + + int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0)); + int type_base = in_bytes(ParametersTypeData::type_offset(0)); + int per_arg_scale = exact_log2(DataLayout::cell_size); + add(t0, mdp, off_base); + add(t1, mdp, type_base); + + shadd(tmp2, tmp1, t0, tmp2, per_arg_scale); + // load offset on the stack from the slot for this parameter + ld(tmp2, Address(tmp2, 0)); + neg(tmp2, tmp2); + + // read the parameter from the local area + shadd(tmp2, tmp2, xlocals, tmp2, Interpreter::logStackElementSize); + ld(tmp2, Address(tmp2, 0)); + + // profile the parameter + shadd(t1, tmp1, t1, t0, per_arg_scale); + Address arg_type(t1, 0); + profile_obj_type(tmp2, arg_type, tmp3); + + // go to next parameter + add(tmp1, tmp1, - TypeStackSlotEntries::per_arg_count()); + bgez(tmp1, loop); + + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::get_method_counters(Register method, + Register mcs, Label& skip) { + Label has_counters; + ld(mcs, Address(method, Method::method_counters_offset())); + bnez(mcs, has_counters); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::build_method_counters), method); + ld(mcs, Address(method, Method::method_counters_offset())); + beqz(mcs, skip); // No MethodCounters allocated, OutOfMemory + bind(has_counters); +} + +#ifdef ASSERT +void InterpreterMacroAssembler::verify_access_flags(Register access_flags, uint32_t flag_bits, + const char* msg, bool stop_by_hit) { + Label L; + andi(t0, access_flags, flag_bits); + if (stop_by_hit) { + beqz(t0, L); + } else { + bnez(t0, L); + } + stop(msg); + bind(L); +} + +void InterpreterMacroAssembler::verify_frame_setup() { + Label L; + const Address monitor_block_top(fp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + ld(t0, monitor_block_top); + beq(esp, t0, L); + stop("broken stack frame setup in interpreter"); + bind(L); +} +#endif diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4d8cb086f829f1a661de480a15f0701a6bbba6e4 --- /dev/null +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_INTERP_MASM_RISCV_HPP +#define CPU_RISCV_INTERP_MASM_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "interpreter/invocationCounter.hpp" +#include "runtime/frame.hpp" + +// This file specializes the assember with interpreter-specific macros + +typedef ByteSize (*OffsetFunction)(uint); + +class InterpreterMacroAssembler: public MacroAssembler { + protected: + // Interpreter specific version of call_VM_base + using MacroAssembler::call_VM_leaf_base; + + virtual void call_VM_leaf_base(address entry_point, + int number_of_arguments); + + virtual void call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions); + + // base routine for all dispatches + void dispatch_base(TosState state, address* table, bool verifyoop = true, + bool generate_poll = false, Register Rs = t0); + + public: + InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {} + virtual ~InterpreterMacroAssembler() {} + + void load_earlyret_value(TosState state); + + void jump_to_entry(address entry); + + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + + // Interpreter-specific registers + void save_bcp() { + sd(xbcp, Address(fp, frame::interpreter_frame_bcp_offset * wordSize)); + } + + void restore_bcp() { + ld(xbcp, Address(fp, frame::interpreter_frame_bcp_offset * wordSize)); + } + + void restore_locals() { + ld(xlocals, Address(fp, frame::interpreter_frame_locals_offset * wordSize)); + } + + void restore_constant_pool_cache() { + ld(xcpool, Address(fp, frame::interpreter_frame_cache_offset * wordSize)); + } + + void get_dispatch(); + + // Helpers for runtime call arguments/results + void get_method(Register reg) { + ld(reg, Address(fp, frame::interpreter_frame_method_offset * wordSize)); + } + + void get_const(Register reg) { + get_method(reg); + ld(reg, Address(reg, in_bytes(Method::const_offset()))); + } + + void get_constant_pool(Register reg) { + get_const(reg); + ld(reg, Address(reg, in_bytes(ConstMethod::constants_offset()))); + } + + void get_constant_pool_cache(Register reg) { + get_constant_pool(reg); + ld(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); + } + + void get_cpool_and_tags(Register cpool, Register tags) { + get_constant_pool(cpool); + ld(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); + } + + void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); + void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); + void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); + void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); + void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); + void get_method_counters(Register method, Register mcs, Label& skip); + + // Load cpool->resolved_references(index). + void load_resolved_reference_at_index(Register result, Register index, Register tmp = x15); + + // Load cpool->resolved_klass_at(index). + void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp); + + void load_resolved_method_at_index(int byte_no, Register method, Register cache); + + void pop_ptr(Register r = x10); + void pop_i(Register r = x10); + void pop_l(Register r = x10); + void pop_f(FloatRegister r = f10); + void pop_d(FloatRegister r = f10); + void push_ptr(Register r = x10); + void push_i(Register r = x10); + void push_l(Register r = x10); + void push_f(FloatRegister r = f10); + void push_d(FloatRegister r = f10); + + void pop(TosState state); // transition vtos -> state + void push(TosState state); // transition state -> vtos + + void empty_expression_stack() { + ld(esp, Address(fp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); + // NULL last_sp until next java call + sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + } + + // Helpers for swap and dup + void load_ptr(int n, Register val); + void store_ptr(int n, Register val); + + // Load float value from 'address'. The value is loaded onto the FPU register v0. + void load_float(Address src); + void load_double(Address src); + + // Generate a subtype check: branch to ok_is_subtype if sub_klass is + // a subtype of super_klass. + void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); + + // Dispatching + void dispatch_prolog(TosState state, int step = 0); + void dispatch_epilog(TosState state, int step = 0); + // dispatch via t0 + void dispatch_only(TosState state, bool generate_poll = false, Register Rs = t0); + // dispatch normal table via t0 (assume t0 is loaded already) + void dispatch_only_normal(TosState state, Register Rs = t0); + void dispatch_only_noverify(TosState state, Register Rs = t0); + // load t0 from [xbcp + step] and dispatch via t0 + void dispatch_next(TosState state, int step = 0, bool generate_poll = false); + // load t0 from [xbcp] and dispatch via t0 and table + void dispatch_via (TosState state, address* table); + + // jump to an invoked target + void prepare_to_jump_from_interpreted(); + void jump_from_interpreted(Register method); + + + // Returning from interpreted functions + // + // Removes the current activation (incl. unlocking of monitors) + // and sets up the return address. This code is also used for + // exception unwindwing. In that case, we do not want to throw + // IllegalMonitorStateExceptions, since that might get us into an + // infinite rethrow exception loop. + // Additionally this code is used for popFrame and earlyReturn. + // In popFrame case we want to skip throwing an exception, + // installing an exception, and notifying jvmdi. + // In earlyReturn case we only want to skip throwing an exception + // and installing an exception. + void remove_activation(TosState state, + bool throw_monitor_exception = true, + bool install_monitor_exception = true, + bool notify_jvmdi = true); + + // FIXME: Give us a valid frame at a null check. + virtual void null_check(Register reg, int offset = -1) { + MacroAssembler::null_check(reg, offset); + } + + // Object locking + void lock_object (Register lock_reg); + void unlock_object(Register lock_reg); + + // Interpreter profiling operations + void set_method_data_pointer_for_bcp(); + void test_method_data_pointer(Register mdp, Label& zero_continue); + void verify_method_data_pointer(); + + void set_mdp_data_at(Register mdp_in, int constant, Register value); + void increment_mdp_data_at(Address data, bool decrement = false); + void increment_mdp_data_at(Register mdp_in, int constant, + 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 tmp1, Register tmp2, + bool preloaded, 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, + Label& not_equal_continue); + + void record_klass_in_profile(Register receiver, Register mdp, + Register reg2, bool is_virtual_call); + void record_klass_in_profile_helper(Register receiver, Register mdp, + Register reg2, + Label& done, bool is_virtual_call); + void record_item_in_profile_helper(Register item, Register mdp, + Register reg2, int start_row, Label& done, int total_rows, + OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, + int non_profiled_offset); + + void update_mdp_by_offset(Register mdp_in, int offset_of_offset); + void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); + void update_mdp_by_constant(Register mdp_in, int constant); + void update_mdp_for_ret(Register return_bci); + + // narrow int return value + void narrow(Register result); + + void profile_taken_branch(Register mdp, Register bumped_count); + void profile_not_taken_branch(Register mdp); + void profile_call(Register mdp); + void profile_final_call(Register mdp); + void profile_virtual_call(Register receiver, Register mdp, + Register t1, + bool receiver_can_be_null = false); + void profile_ret(Register return_bci, Register mdp); + void profile_null_seen(Register mdp); + void profile_typecheck(Register mdp, Register klass, Register temp); + void profile_typecheck_failed(Register mdp); + void profile_switch_default(Register mdp); + void profile_switch_case(Register index_in_scratch, Register mdp, + Register temp); + + void profile_obj_type(Register obj, const Address& mdo_addr, Register tmp); + void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); + void profile_return_type(Register mdp, Register ret, Register tmp); + void profile_parameters_type(Register mdp, Register tmp1, Register tmp2, Register tmp3); + + // Debugging + // only if +VerifyFPU && (state == ftos || state == dtos) + void verify_FPU(int stack_depth, TosState state = ftos); + + typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; + + // support for jvmti/dtrace + void notify_method_entry(); + void notify_method_exit(TosState state, NotifyMethodExitMode mode); + + virtual void _call_Unimplemented(address call_site) { + save_bcp(); + set_last_Java_frame(esp, fp, (address) pc(), t0); + MacroAssembler::_call_Unimplemented(call_site); + } + +#ifdef ASSERT + void verify_access_flags(Register access_flags, uint32_t flag_bits, + const char* msg, bool stop_by_hit = true); + void verify_frame_setup(); +#endif +}; + +#endif // CPU_RISCV_INTERP_MASM_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d93530d85640145aaa8ac76e1e15d95cafc22bb8 --- /dev/null +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/universe.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/icache.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/signature.hpp" + +#define __ _masm-> + +// Implementation of SignatureHandlerGenerator +Register InterpreterRuntime::SignatureHandlerGenerator::from() { return xlocals; } +Register InterpreterRuntime::SignatureHandlerGenerator::to() { return sp; } +Register InterpreterRuntime::SignatureHandlerGenerator::temp() { return t0; } + +Register InterpreterRuntime::SignatureHandlerGenerator::next_gpr() { + if (_num_reg_int_args < Argument::n_int_register_parameters_c - 1) { + return g_INTArgReg[++_num_reg_int_args]; + } + return noreg; +} + +FloatRegister InterpreterRuntime::SignatureHandlerGenerator::next_fpr() { + if (_num_reg_fp_args < Argument::n_float_register_parameters_c) { + return g_FPArgReg[_num_reg_fp_args++]; + } else { + return fnoreg; + } +} + +int InterpreterRuntime::SignatureHandlerGenerator::next_stack_offset() { + int ret = _stack_offset; + _stack_offset += wordSize; + return ret; +} + +InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator( + const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + _masm = new MacroAssembler(buffer); // allocate on resourse area by default + _num_reg_int_args = (method->is_static() ? 1 : 0); + _num_reg_fp_args = 0; + _stack_offset = 0; +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_int() { + const Address src(from(), Interpreter::local_offset_in_bytes(offset())); + + Register reg = next_gpr(); + if (reg != noreg) { + __ lw(reg, src); + } else { + __ lw(x10, src); + __ sw(x10, Address(to(), next_stack_offset())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { + const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); + + Register reg = next_gpr(); + if (reg != noreg) { + __ ld(reg, src); + } else { + __ ld(x10, src); + __ sd(x10, Address(to(), next_stack_offset())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { + const Address src(from(), Interpreter::local_offset_in_bytes(offset())); + + FloatRegister reg = next_fpr(); + if (reg != fnoreg) { + __ flw(reg, src); + } else { + // a floating-point argument is passed according to the integer calling + // convention if no floating-point argument register available + pass_int(); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { + const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); + + FloatRegister reg = next_fpr(); + if (reg != fnoreg) { + __ fld(reg, src); + } else { + // a floating-point argument is passed according to the integer calling + // convention if no floating-point argument register available + pass_long(); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { + Register reg = next_gpr(); + if (reg == c_rarg1) { + assert(offset() == 0, "argument register 1 can only be (non-null) receiver"); + __ addi(c_rarg1, from(), Interpreter::local_offset_in_bytes(offset())); + } else if (reg != noreg) { + // c_rarg2-c_rarg7 + __ addi(x10, from(), Interpreter::local_offset_in_bytes(offset())); + __ mv(reg, zr); //_num_reg_int_args:c_rarg -> 1:c_rarg2, 2:c_rarg3... + __ ld(temp(), x10); + Label L; + __ beqz(temp(), L); + __ mv(reg, x10); + __ bind(L); + } else { + //to stack + __ addi(x10, from(), Interpreter::local_offset_in_bytes(offset())); + __ ld(temp(), x10); + Label L; + __ bnez(temp(), L); + __ mv(x10, zr); + __ bind(L); + assert(sizeof(jobject) == wordSize, ""); + __ sd(x10, Address(to(), next_stack_offset())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) { + // generate code to handle arguments + iterate(fingerprint); + + // return result handler + __ la(x10, ExternalAddress(Interpreter::result_handler(method()->result_type()))); + __ ret(); + + __ flush(); +} + + +// Implementation of SignatureHandlerLibrary + +void SignatureHandlerLibrary::pd_set_handler(address handler) {} + + +class SlowSignatureHandler + : public NativeSignatureIterator { + private: + address _from; + intptr_t* _to; + intptr_t* _int_args; + intptr_t* _fp_args; + intptr_t* _fp_identifiers; + unsigned int _num_reg_int_args; + unsigned int _num_reg_fp_args; + + intptr_t* single_slot_addr() { + intptr_t* from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); + _from -= Interpreter::stackElementSize; + return from_addr; + } + + intptr_t* double_slot_addr() { + intptr_t* from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(1)); + _from -= 2 * Interpreter::stackElementSize; + return from_addr; + } + + int pass_gpr(intptr_t value) { + if (_num_reg_int_args < Argument::n_int_register_parameters_c - 1) { + *_int_args++ = value; + return _num_reg_int_args++; + } + return -1; + } + + int pass_fpr(intptr_t value) { + if (_num_reg_fp_args < Argument::n_float_register_parameters_c) { + *_fp_args++ = value; + return _num_reg_fp_args++; + } + return -1; + } + + void pass_stack(intptr_t value) { + *_to++ = value; + } + + virtual void pass_int() { + jint value = *(jint*)single_slot_addr(); + if (pass_gpr(value) < 0) { + pass_stack(value); + } + } + + virtual void pass_long() { + intptr_t value = *double_slot_addr(); + if (pass_gpr(value) < 0) { + pass_stack(value); + } + } + + virtual void pass_object() { + intptr_t* addr = single_slot_addr(); + intptr_t value = *addr == 0 ? NULL : (intptr_t)addr; + if (pass_gpr(value) < 0) { + pass_stack(value); + } + } + + virtual void pass_float() { + jint value = *(jint*) single_slot_addr(); + // a floating-point argument is passed according to the integer calling + // convention if no floating-point argument register available + if (pass_fpr(value) < 0 && pass_gpr(value) < 0) { + pass_stack(value); + } + } + + virtual void pass_double() { + intptr_t value = *double_slot_addr(); + int arg = pass_fpr(value); + if (0 <= arg) { + *_fp_identifiers |= (1ull << arg); // mark as double + } else if (pass_gpr(value) < 0) { // no need to mark if passing by integer registers or stack + pass_stack(value); + } + } + + public: + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) + : NativeSignatureIterator(method) + { + _from = from; + _to = to; + + _int_args = to - (method->is_static() ? 16 : 17); + _fp_args = to - 8; + _fp_identifiers = to - 9; + *(int*) _fp_identifiers = 0; + _num_reg_int_args = (method->is_static() ? 1 : 0); + _num_reg_fp_args = 0; + } + + ~SlowSignatureHandler() + { + _from = NULL; + _to = NULL; + _int_args = NULL; + _fp_args = NULL; + _fp_identifiers = NULL; + } +}; + + +JRT_ENTRY(address, + InterpreterRuntime::slow_signature_handler(JavaThread* current, + Method* method, + intptr_t* from, + intptr_t* to)) + methodHandle m(current, (Method*)method); + assert(m->is_native(), "sanity check"); + + // handle arguments + SlowSignatureHandler ssh(m, (address)from, to); + ssh.iterate(UCONST64(-1)); + + // return result handler + return Interpreter::result_handler(m->result_type()); +JRT_END diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..05df63ba2ae5f1ef079019d4382f8fec774cd39c --- /dev/null +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_INTERPRETERRT_RISCV_HPP +#define CPU_RISCV_INTERPRETERRT_RISCV_HPP + +// This is included in the middle of class Interpreter. +// Do not include files here. + +// native method calls + +class SignatureHandlerGenerator: public NativeSignatureIterator { + private: + MacroAssembler* _masm; + unsigned int _num_reg_fp_args; + unsigned int _num_reg_int_args; + int _stack_offset; + + void pass_int(); + void pass_long(); + void pass_float(); + void pass_double(); + void pass_object(); + + Register next_gpr(); + FloatRegister next_fpr(); + int next_stack_offset(); + + public: + // Creation + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer); + virtual ~SignatureHandlerGenerator() { + _masm = NULL; + } + + // Code generation + void generate(uint64_t fingerprint); + + // Code generation support + static Register from(); + static Register to(); + static Register temp(); +}; + +#endif // CPU_RISCV_INTERPRETERRT_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9a6084afa1dee3832a7987af9f295bdc5042e970 --- /dev/null +++ b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_JAVAFRAMEANCHOR_RISCV_HPP +#define CPU_RISCV_JAVAFRAMEANCHOR_RISCV_HPP + +private: + + // FP value associated with _last_Java_sp: + intptr_t* volatile _last_Java_fp; // pointer is volatile not what it points to + +public: + // Each arch must define reset, save, restore + // These are used by objects that only care about: + // 1 - initializing a new state (thread creation, javaCalls) + // 2 - saving a current state (javaCalls) + // 3 - restoring an old state (javaCalls) + + void clear(void) { + // clearing _last_Java_sp must be first + _last_Java_sp = NULL; + OrderAccess::release(); + _last_Java_fp = NULL; + _last_Java_pc = NULL; + } + + void copy(JavaFrameAnchor* src) { + // In order to make sure the transition state is valid for "this" + // We must clear _last_Java_sp before copying the rest of the new data + // + // Hack Alert: Temporary bugfix for 4717480/4721647 + // To act like previous version (pd_cache_state) don't NULL _last_Java_sp + // unless the value is changing + // + assert(src != NULL, "Src should not be NULL."); + if (_last_Java_sp != src->_last_Java_sp) { + _last_Java_sp = NULL; + OrderAccess::release(); + } + _last_Java_fp = src->_last_Java_fp; + _last_Java_pc = src->_last_Java_pc; + // Must be last so profiler will always see valid frame if has_last_frame() is true + _last_Java_sp = src->_last_Java_sp; + } + + bool walkable(void) { return _last_Java_sp != NULL && _last_Java_pc != NULL; } + void make_walkable(JavaThread* thread); + void capture_last_Java_pc(void); + + intptr_t* last_Java_sp(void) const { return _last_Java_sp; } + + const address last_Java_pc(void) { return _last_Java_pc; } + +private: + + static ByteSize last_Java_fp_offset() { return byte_offset_of(JavaFrameAnchor, _last_Java_fp); } + +public: + + void set_last_Java_sp(intptr_t* java_sp) { _last_Java_sp = java_sp; OrderAccess::release(); } + + intptr_t* last_Java_fp(void) { return _last_Java_fp; } + +#endif // CPU_RISCV_JAVAFRAMEANCHOR_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..814ed23e471a26bb50100388fcbe08eb97f9aa5e --- /dev/null +++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "memory/resourceArea.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm_misc.hpp" +#include "prims/jvmtiExport.hpp" +#include "runtime/safepoint.hpp" + +#define __ masm-> + +#define BUFFER_SIZE 30*wordSize + +// Instead of issuing a LoadLoad barrier we create an address +// dependency between loads; this might be more efficient. + +// Common register usage: +// x10/f10: result +// c_rarg0: jni env +// c_rarg1: obj +// c_rarg2: jfield id + +static const Register robj = x13; +static const Register rcounter = x14; +static const Register roffset = x15; +static const Register rcounter_addr = x16; +static const Register result = x17; + +address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { + const char *name; + switch (type) { + case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; + case T_BYTE: name = "jni_fast_GetByteField"; break; + case T_CHAR: name = "jni_fast_GetCharField"; break; + case T_SHORT: name = "jni_fast_GetShortField"; break; + case T_INT: name = "jni_fast_GetIntField"; break; + case T_LONG: name = "jni_fast_GetLongField"; break; + case T_FLOAT: name = "jni_fast_GetFloatField"; break; + case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; + default: ShouldNotReachHere(); + name = NULL; // unreachable + } + ResourceMark rm; + BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); + CodeBuffer cbuf(blob); + MacroAssembler* masm = new MacroAssembler(&cbuf); + address fast_entry = __ pc(); + + Label slow; + int32_t offset = 0; + __ la_patchable(rcounter_addr, SafepointSynchronize::safepoint_counter_addr(), offset); + __ addi(rcounter_addr, rcounter_addr, offset); + + Address safepoint_counter_addr(rcounter_addr, 0); + __ lwu(rcounter, safepoint_counter_addr); + // An even value means there are no ongoing safepoint operations + __ andi(t0, rcounter, 1); + __ bnez(t0, slow); + + if (JvmtiExport::can_post_field_access()) { + // Using barrier to order wrt. JVMTI check and load of result. + __ membar(MacroAssembler::LoadLoad); + + // Check to see if a field access watch has been set before we + // take the fast path. + int32_t offset2; + __ la_patchable(result, + ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), + offset2); + __ lwu(result, Address(result, offset2)); + __ bnez(result, slow); + + __ mv(robj, c_rarg1); + } else { + // Using address dependency to order wrt. load of result. + __ xorr(robj, c_rarg1, rcounter); + __ xorr(robj, robj, rcounter); // obj, since + // robj ^ rcounter ^ rcounter == robj + // robj is address dependent on rcounter. + } + + // Both robj and t0 are clobbered by try_resolve_jobject_in_native. + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + assert_cond(bs != NULL); + bs->try_resolve_jobject_in_native(masm, c_rarg0, robj, t0, slow); + + __ srli(roffset, c_rarg2, 2); // offset + + assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); + speculative_load_pclist[count] = __ pc(); // Used by the segfault handler + __ add(roffset, robj, roffset); + + switch (type) { + case T_BOOLEAN: __ lbu(result, Address(roffset, 0)); break; + case T_BYTE: __ lb(result, Address(roffset, 0)); break; + case T_CHAR: __ lhu(result, Address(roffset, 0)); break; + case T_SHORT: __ lh(result, Address(roffset, 0)); break; + case T_INT: __ lw(result, Address(roffset, 0)); break; + case T_LONG: __ ld(result, Address(roffset, 0)); break; + case T_FLOAT: { + __ flw(f28, Address(roffset, 0)); // f28 as temporaries + __ fmv_x_w(result, f28); // f{31--0}-->x + break; + } + case T_DOUBLE: { + __ fld(f28, Address(roffset, 0)); // f28 as temporaries + __ fmv_x_d(result, f28); // d{63--0}-->x + break; + } + default: ShouldNotReachHere(); + } + + // Using acquire: Order JVMTI check and load of result wrt. succeeding check + // (LoadStore for volatile field). + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + + __ lw(t0, safepoint_counter_addr); + __ bne(rcounter, t0, slow); + + switch (type) { + case T_FLOAT: __ fmv_w_x(f10, result); break; + case T_DOUBLE: __ fmv_d_x(f10, result); break; + default: __ mv(x10, result); break; + } + __ ret(); + + slowcase_entry_pclist[count++] = __ pc(); + __ bind(slow); + address slow_case_addr; + switch (type) { + case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; + case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; + case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; + case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; + case T_INT: slow_case_addr = jni_GetIntField_addr(); break; + case T_LONG: slow_case_addr = jni_GetLongField_addr(); break; + case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; + case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; + default: ShouldNotReachHere(); + slow_case_addr = NULL; // unreachable + } + + { + __ enter(); + int32_t tmp_offset = 0; + __ la_patchable(t0, ExternalAddress(slow_case_addr), tmp_offset); + __ jalr(x1, t0, tmp_offset); + __ leave(); + __ ret(); + } + __ flush(); + + return fast_entry; +} + + +address JNI_FastGetField::generate_fast_get_boolean_field() { + return generate_fast_get_int_field0(T_BOOLEAN); +} + +address JNI_FastGetField::generate_fast_get_byte_field() { + return generate_fast_get_int_field0(T_BYTE); +} + +address JNI_FastGetField::generate_fast_get_char_field() { + return generate_fast_get_int_field0(T_CHAR); +} + +address JNI_FastGetField::generate_fast_get_short_field() { + return generate_fast_get_int_field0(T_SHORT); +} + +address JNI_FastGetField::generate_fast_get_int_field() { + return generate_fast_get_int_field0(T_INT); +} + +address JNI_FastGetField::generate_fast_get_long_field() { + return generate_fast_get_int_field0(T_LONG); +} + +address JNI_FastGetField::generate_fast_get_float_field() { + return generate_fast_get_int_field0(T_FLOAT); +} + +address JNI_FastGetField::generate_fast_get_double_field() { + return generate_fast_get_int_field0(T_DOUBLE); +} diff --git a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..83ffcc55d835525a7e58af5c3be9fecea833a2c3 --- /dev/null +++ b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_JNITYPES_RISCV_HPP +#define CPU_RISCV_JNITYPES_RISCV_HPP + +#include "jni.h" +#include "memory/allStatic.hpp" +#include "oops/oop.hpp" + +// This file holds platform-dependent routines used to write primitive jni +// types to the array of arguments passed into JavaCalls::call + +class JNITypes : private AllStatic { + // These functions write a java primitive type (in native format) + // to a java stack slot array to be passed as an argument to JavaCalls:calls. + // I.e., they are functionally 'push' operations if they have a 'pos' + // formal parameter. Note that jlong's and jdouble's are written + // _in reverse_ of the order in which they appear in the interpreter + // stack. This is because call stubs (see stubGenerator_sparc.cpp) + // reverse the argument list constructed by JavaCallArguments (see + // javaCalls.hpp). + +public: + // Ints are stored in native format in one JavaCallArgument slot at *to. + static inline void put_int(jint from, intptr_t *to) { *(jint *)(to + 0 ) = from; } + static inline void put_int(jint from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = from; } + static inline void put_int(jint *from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = *from; } + + // Longs are stored in native format in one JavaCallArgument slot at + // *(to+1). + static inline void put_long(jlong from, intptr_t *to) { + *(jlong*) (to + 1) = from; + } + + static inline void put_long(jlong from, intptr_t *to, int& pos) { + *(jlong*) (to + 1 + pos) = from; + pos += 2; + } + + static inline void put_long(jlong *from, intptr_t *to, int& pos) { + *(jlong*) (to + 1 + pos) = *from; + pos += 2; + } + + // Oops are stored in native format in one JavaCallArgument slot at *to. + static inline void put_obj(const Handle& from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle.raw_value(); } + static inline void put_obj(jobject from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle; } + + // Floats are stored in native format in one JavaCallArgument slot at *to. + static inline void put_float(jfloat from, intptr_t *to) { *(jfloat *)(to + 0 ) = from; } + static inline void put_float(jfloat from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = from; } + static inline void put_float(jfloat *from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = *from; } + +#undef _JNI_SLOT_OFFSET +#define _JNI_SLOT_OFFSET 1 + // Doubles are stored in native word format in one JavaCallArgument + // slot at *(to+1). + static inline void put_double(jdouble from, intptr_t *to) { + *(jdouble*) (to + 1) = from; + } + + static inline void put_double(jdouble from, intptr_t *to, int& pos) { + *(jdouble*) (to + 1 + pos) = from; + pos += 2; + } + + static inline void put_double(jdouble *from, intptr_t *to, int& pos) { + *(jdouble*) (to + 1 + pos) = *from; + pos += 2; + } + + // The get_xxx routines, on the other hand, actually _do_ fetch + // java primitive types from the interpreter stack. + // No need to worry about alignment on Intel. + static inline jint get_int (intptr_t *from) { return *(jint *) from; } + static inline jlong get_long (intptr_t *from) { return *(jlong *) (from + _JNI_SLOT_OFFSET); } + static inline oop get_obj (intptr_t *from) { return *(oop *) from; } + static inline jfloat get_float (intptr_t *from) { return *(jfloat *) from; } + static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); } +#undef _JNI_SLOT_OFFSET +}; + +#endif // CPU_RISCV_JNITYPES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d830405db21deb91f3f9a79109d3e26747a58e46 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -0,0 +1,4019 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/assembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/cardTableBarrierSet.hpp" +#include "interpreter/bytecodeHistogram.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/accessDecorators.hpp" +#include "oops/compressedOops.inline.hpp" +#include "oops/klass.inline.hpp" +#include "oops/oop.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.hpp" +#include "utilities/powerOfTwo.hpp" +#ifdef COMPILER2 +#include "opto/compile.hpp" +#include "opto/node.hpp" +#include "opto/output.hpp" +#endif + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) block_comment(str) +#endif +#define BIND(label) bind(label); __ BLOCK_COMMENT(#label ":") + +static void pass_arg0(MacroAssembler* masm, Register arg) { + if (c_rarg0 != arg) { + assert_cond(masm != NULL); + masm->mv(c_rarg0, arg); + } +} + +static void pass_arg1(MacroAssembler* masm, Register arg) { + if (c_rarg1 != arg) { + assert_cond(masm != NULL); + masm->mv(c_rarg1, arg); + } +} + +static void pass_arg2(MacroAssembler* masm, Register arg) { + if (c_rarg2 != arg) { + assert_cond(masm != NULL); + masm->mv(c_rarg2, arg); + } +} + +static void pass_arg3(MacroAssembler* masm, Register arg) { + if (c_rarg3 != arg) { + assert_cond(masm != NULL); + masm->mv(c_rarg3, arg); + } +} + +void MacroAssembler::align(int modulus, int extra_offset) { + CompressibleRegion cr(this); + while ((offset() + extra_offset) % modulus != 0) { nop(); } +} + +void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { + call_VM_base(oop_result, noreg, noreg, entry_point, number_of_arguments, check_exceptions); +} + +// Implementation of call_VM versions + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + bool check_exceptions) { + call_VM_helper(oop_result, entry_point, 0, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + bool check_exceptions) { + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 1, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 2, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + assert(arg_1 != c_rarg3, "smashed arg"); + assert(arg_2 != c_rarg3, "smashed arg"); + pass_arg3(this, arg_3); + + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 3, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + call_VM_base(oop_result, xthread, last_java_sp, entry_point, number_of_arguments, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + bool check_exceptions) { + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + assert(arg_1 != c_rarg3, "smashed arg"); + assert(arg_2 != c_rarg3, "smashed arg"); + pass_arg3(this, arg_3); + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); +} + +// these are no-ops overridden by InterpreterMacroAssembler +void MacroAssembler::check_and_handle_earlyret(Register java_thread) {} +void MacroAssembler::check_and_handle_popframe(Register java_thread) {} + +// Calls to C land +// +// When entering C land, the fp, & esp of the last Java frame have to be recorded +// in the (thread-local) JavaThread object. When leaving C land, the last Java fp +// has to be reset to 0. This is required to allow proper stack traversal. +void MacroAssembler::set_last_Java_frame(Register last_java_sp, + Register last_java_fp, + Register last_java_pc, + Register tmp) { + + if (last_java_pc->is_valid()) { + sd(last_java_pc, Address(xthread, + JavaThread::frame_anchor_offset() + + JavaFrameAnchor::last_Java_pc_offset())); + } + + // determine last_java_sp register + if (last_java_sp == sp) { + mv(tmp, sp); + last_java_sp = tmp; + } else if (!last_java_sp->is_valid()) { + last_java_sp = esp; + } + + sd(last_java_sp, Address(xthread, JavaThread::last_Java_sp_offset())); + + // last_java_fp is optional + if (last_java_fp->is_valid()) { + sd(last_java_fp, Address(xthread, JavaThread::last_Java_fp_offset())); + } +} + +void MacroAssembler::set_last_Java_frame(Register last_java_sp, + Register last_java_fp, + address last_java_pc, + Register tmp) { + assert(last_java_pc != NULL, "must provide a valid PC"); + + la(tmp, last_java_pc); + sd(tmp, Address(xthread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset())); + + set_last_Java_frame(last_java_sp, last_java_fp, noreg, tmp); +} + +void MacroAssembler::set_last_Java_frame(Register last_java_sp, + Register last_java_fp, + Label &L, + Register tmp) { + if (L.is_bound()) { + set_last_Java_frame(last_java_sp, last_java_fp, target(L), tmp); + } else { + InstructionMark im(this); + L.add_patch_at(code(), locator()); + set_last_Java_frame(last_java_sp, last_java_fp, pc() /* Patched later */, tmp); + } +} + +void MacroAssembler::reset_last_Java_frame(bool clear_fp) { + // we must set sp to zero to clear frame + sd(zr, Address(xthread, JavaThread::last_Java_sp_offset())); + + // must clear fp, so that compiled frames are not confused; it is + // possible that we need it only for debugging + if (clear_fp) { + sd(zr, Address(xthread, JavaThread::last_Java_fp_offset())); + } + + // Always clear the pc because it could have been set by make_walkable() + sd(zr, Address(xthread, JavaThread::last_Java_pc_offset())); +} + +void MacroAssembler::call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + // determine java_thread register + if (!java_thread->is_valid()) { + java_thread = xthread; + } + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + last_java_sp = esp; + } + + // debugging support + assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); + assert(java_thread == xthread, "unexpected register"); + + assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); + assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp"); + + // push java thread (becomes first argument of C function) + mv(c_rarg0, java_thread); + + // set last Java frame before call + assert(last_java_sp != fp, "can't use fp"); + + Label l; + set_last_Java_frame(last_java_sp, fp, l, t0); + + // do the call, remove parameters + MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments, &l); + + // reset last Java frame + // Only interpreter should have to clear fp + reset_last_Java_frame(true); + + // C++ interp handles this in the interpreter + check_and_handle_popframe(java_thread); + check_and_handle_earlyret(java_thread); + + if (check_exceptions) { + // check for pending exceptions (java_thread is set upon return) + ld(t0, Address(java_thread, in_bytes(Thread::pending_exception_offset()))); + Label ok; + beqz(t0, ok); + int32_t offset = 0; + la_patchable(t0, RuntimeAddress(StubRoutines::forward_exception_entry()), offset); + jalr(x0, t0, offset); + bind(ok); + } + + // get oop result if there is one and reset the value in the thread + if (oop_result->is_valid()) { + get_vm_result(oop_result, java_thread); + } +} + +void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { + ld(oop_result, Address(java_thread, JavaThread::vm_result_offset())); + sd(zr, Address(java_thread, JavaThread::vm_result_offset())); + verify_oop(oop_result, "broken oop in call_VM_base"); +} + +void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { + ld(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); + sd(zr, Address(java_thread, JavaThread::vm_result_2_offset())); +} + +void MacroAssembler::clinit_barrier(Register klass, Register tmp, Label* L_fast_path, Label* L_slow_path) { + assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required"); + assert_different_registers(klass, xthread, tmp); + + Label L_fallthrough, L_tmp; + if (L_fast_path == NULL) { + L_fast_path = &L_fallthrough; + } else if (L_slow_path == NULL) { + L_slow_path = &L_fallthrough; + } + + // Fast path check: class is fully initialized + lbu(tmp, Address(klass, InstanceKlass::init_state_offset())); + sub(tmp, tmp, InstanceKlass::fully_initialized); + beqz(tmp, *L_fast_path); + + // Fast path check: current thread is initializer thread + ld(tmp, Address(klass, InstanceKlass::init_thread_offset())); + + if (L_slow_path == &L_fallthrough) { + beq(xthread, tmp, *L_fast_path); + bind(*L_slow_path); + } else if (L_fast_path == &L_fallthrough) { + bne(xthread, tmp, *L_slow_path); + bind(*L_fast_path); + } else { + Unimplemented(); + } +} + +void MacroAssembler::verify_oop(Register reg, const char* s) { + if (!VerifyOops) { return; } + + // Pass register number to verify_oop_subroutine + const char* b = NULL; + { + ResourceMark rm; + stringStream ss; + ss.print("verify_oop: %s: %s", reg->name(), s); + b = code_string(ss.as_string()); + } + BLOCK_COMMENT("verify_oop {"); + + push_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); + + mv(c_rarg0, reg); // c_rarg0 : x10 + li(t0, (uintptr_t)(address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; + la_patchable(t1, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address()), offset); + ld(t1, Address(t1, offset)); + jalr(t1); + + pop_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); + + BLOCK_COMMENT("} verify_oop"); +} + +void MacroAssembler::verify_oop_addr(Address addr, const char* s) { + if (!VerifyOops) { + return; + } + + const char* b = NULL; + { + ResourceMark rm; + stringStream ss; + ss.print("verify_oop_addr: %s", s); + b = code_string(ss.as_string()); + } + BLOCK_COMMENT("verify_oop_addr {"); + + push_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); + + if (addr.uses(sp)) { + la(x10, addr); + ld(x10, Address(x10, 4 * wordSize)); + } else { + ld(x10, addr); + } + + li(t0, (uintptr_t)(address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; + la_patchable(t1, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address()), offset); + ld(t1, Address(t1, offset)); + jalr(t1); + + pop_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); + + BLOCK_COMMENT("} verify_oop_addr"); +} + +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, + int extra_slot_offset) { + // cf. TemplateTable::prepare_invoke(), if (load_receiver). + int stackElementSize = Interpreter::stackElementSize; + int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); +#ifdef ASSERT + int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); + assert(offset1 - offset == stackElementSize, "correct arithmetic"); +#endif + if (arg_slot.is_constant()) { + return Address(esp, arg_slot.as_constant() * stackElementSize + offset); + } else { + assert_different_registers(t0, arg_slot.as_register()); + shadd(t0, arg_slot.as_register(), esp, t0, exact_log2(stackElementSize)); + return Address(t0, offset); + } +} + +#ifndef PRODUCT +extern "C" void findpc(intptr_t x); +#endif + +void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) +{ + // In order to get locks to work, we need to fake a in_VM state + if (ShowMessageBoxOnError) { + JavaThread* thread = JavaThread::current(); + JavaThreadState saved_state = thread->thread_state(); + thread->set_thread_state(_thread_in_vm); +#ifndef PRODUCT + if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + ttyLocker ttyl; + BytecodeCounter::print(); + } +#endif + if (os::message_box(msg, "Execution stopped, print registers?")) { + ttyLocker ttyl; + tty->print_cr(" pc = 0x%016lx", pc); +#ifndef PRODUCT + tty->cr(); + findpc(pc); + tty->cr(); +#endif + tty->print_cr(" x0 = 0x%016lx", regs[0]); + tty->print_cr(" x1 = 0x%016lx", regs[1]); + tty->print_cr(" x2 = 0x%016lx", regs[2]); + tty->print_cr(" x3 = 0x%016lx", regs[3]); + tty->print_cr(" x4 = 0x%016lx", regs[4]); + tty->print_cr(" x5 = 0x%016lx", regs[5]); + tty->print_cr(" x6 = 0x%016lx", regs[6]); + tty->print_cr(" x7 = 0x%016lx", regs[7]); + tty->print_cr(" x8 = 0x%016lx", regs[8]); + tty->print_cr(" x9 = 0x%016lx", regs[9]); + tty->print_cr("x10 = 0x%016lx", regs[10]); + tty->print_cr("x11 = 0x%016lx", regs[11]); + tty->print_cr("x12 = 0x%016lx", regs[12]); + tty->print_cr("x13 = 0x%016lx", regs[13]); + tty->print_cr("x14 = 0x%016lx", regs[14]); + tty->print_cr("x15 = 0x%016lx", regs[15]); + tty->print_cr("x16 = 0x%016lx", regs[16]); + tty->print_cr("x17 = 0x%016lx", regs[17]); + tty->print_cr("x18 = 0x%016lx", regs[18]); + tty->print_cr("x19 = 0x%016lx", regs[19]); + tty->print_cr("x20 = 0x%016lx", regs[20]); + tty->print_cr("x21 = 0x%016lx", regs[21]); + tty->print_cr("x22 = 0x%016lx", regs[22]); + tty->print_cr("x23 = 0x%016lx", regs[23]); + tty->print_cr("x24 = 0x%016lx", regs[24]); + tty->print_cr("x25 = 0x%016lx", regs[25]); + tty->print_cr("x26 = 0x%016lx", regs[26]); + tty->print_cr("x27 = 0x%016lx", regs[27]); + tty->print_cr("x28 = 0x%016lx", regs[28]); + tty->print_cr("x30 = 0x%016lx", regs[30]); + tty->print_cr("x31 = 0x%016lx", regs[31]); + BREAKPOINT; + } + } + fatal("DEBUG MESSAGE: %s", msg); +} + +void MacroAssembler::resolve_jobject(Register value, Register thread, Register tmp) { + Label done, not_weak; + beqz(value, done); // Use NULL as-is. + + // Test for jweak tag. + andi(t0, value, JNIHandles::weak_tag_mask); + beqz(t0, not_weak); + + // Resolve jweak. + access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, value, + Address(value, -JNIHandles::weak_tag_value), tmp, thread); + verify_oop(value); + j(done); + + bind(not_weak); + // Resolve (untagged) jobject. + access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread); + verify_oop(value); + bind(done); +} + +void MacroAssembler::stop(const char* msg) { + address ip = pc(); + pusha(); + // The length of the instruction sequence emitted should be independent + // of the values of msg and ip so that the size of mach nodes for scratch + // emit and normal emit matches. + mv(c_rarg0, (address)msg); + mv(c_rarg1, (address)ip); + mv(c_rarg2, sp); + mv(c_rarg3, CAST_FROM_FN_PTR(address, MacroAssembler::debug64)); + jalr(c_rarg3); + ebreak(); +} + +void MacroAssembler::unimplemented(const char* what) { + const char* buf = NULL; + { + ResourceMark rm; + stringStream ss; + ss.print("unimplemented: %s", what); + buf = code_string(ss.as_string()); + } + stop(buf); +} + +void MacroAssembler::emit_static_call_stub() { + // CompiledDirectStaticCall::set_to_interpreted knows the + // exact layout of this stub. + + ifence(); + mov_metadata(xmethod, (Metadata*)NULL); + + // Jump to the entry point of the i2c stub. + int32_t offset = 0; + movptr_with_offset(t0, 0, offset); + jalr(x0, t0, offset); +} + +void MacroAssembler::call_VM_leaf_base(address entry_point, + int number_of_arguments, + Label *retaddr) { + call_native_base(entry_point, retaddr); +} + +void MacroAssembler::call_native(address entry_point, Register arg_0) { + pass_arg0(this, arg_0); + call_native_base(entry_point); +} + +void MacroAssembler::call_native_base(address entry_point, Label *retaddr) { + Label E, L; + int32_t offset = 0; + push_reg(0x80000040, sp); // push << t0 & xmethod >> to sp + movptr_with_offset(t0, entry_point, offset); + jalr(x1, t0, offset); + if (retaddr != NULL) { + bind(*retaddr); + } + pop_reg(0x80000040, sp); // pop << t0 & xmethod >> from sp +} + +void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { + call_VM_leaf_base(entry_point, number_of_arguments); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0) { + pass_arg0(this, arg_0); + call_VM_leaf_base(entry_point, 1); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { + pass_arg0(this, arg_0); + pass_arg1(this, arg_1); + call_VM_leaf_base(entry_point, 2); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, + Register arg_1, Register arg_2) { + pass_arg0(this, arg_0); + pass_arg1(this, arg_1); + pass_arg2(this, arg_2); + call_VM_leaf_base(entry_point, 3); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) { + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 1); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { + + assert(arg_0 != c_rarg1, "smashed arg"); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 2); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { + assert(arg_0 != c_rarg2, "smashed arg"); + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + assert(arg_0 != c_rarg1, "smashed arg"); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 3); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) { + assert(arg_0 != c_rarg3, "smashed arg"); + assert(arg_1 != c_rarg3, "smashed arg"); + assert(arg_2 != c_rarg3, "smashed arg"); + pass_arg3(this, arg_3); + assert(arg_0 != c_rarg2, "smashed arg"); + assert(arg_1 != c_rarg2, "smashed arg"); + pass_arg2(this, arg_2); + assert(arg_0 != c_rarg1, "smashed arg"); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 4); +} + +void MacroAssembler::nop() { + addi(x0, x0, 0); +} + +void MacroAssembler::mv(Register Rd, Register Rs) { + if (Rd != Rs) { + addi(Rd, Rs, 0); + } +} + +void MacroAssembler::notr(Register Rd, Register Rs) { + xori(Rd, Rs, -1); +} + +void MacroAssembler::neg(Register Rd, Register Rs) { + sub(Rd, x0, Rs); +} + +void MacroAssembler::negw(Register Rd, Register Rs) { + subw(Rd, x0, Rs); +} + +void MacroAssembler::sext_w(Register Rd, Register Rs) { + addiw(Rd, Rs, 0); +} + +void MacroAssembler::zext_b(Register Rd, Register Rs) { + andi(Rd, Rs, 0xFF); +} + +void MacroAssembler::seqz(Register Rd, Register Rs) { + sltiu(Rd, Rs, 1); +} + +void MacroAssembler::snez(Register Rd, Register Rs) { + sltu(Rd, x0, Rs); +} + +void MacroAssembler::sltz(Register Rd, Register Rs) { + slt(Rd, Rs, x0); +} + +void MacroAssembler::sgtz(Register Rd, Register Rs) { + slt(Rd, x0, Rs); +} + +void MacroAssembler::fmv_s(FloatRegister Rd, FloatRegister Rs) { + if (Rd != Rs) { + fsgnj_s(Rd, Rs, Rs); + } +} + +void MacroAssembler::fabs_s(FloatRegister Rd, FloatRegister Rs) { + fsgnjx_s(Rd, Rs, Rs); +} + +void MacroAssembler::fneg_s(FloatRegister Rd, FloatRegister Rs) { + fsgnjn_s(Rd, Rs, Rs); +} + +void MacroAssembler::fmv_d(FloatRegister Rd, FloatRegister Rs) { + if (Rd != Rs) { + fsgnj_d(Rd, Rs, Rs); + } +} + +void MacroAssembler::fabs_d(FloatRegister Rd, FloatRegister Rs) { + fsgnjx_d(Rd, Rs, Rs); +} + +void MacroAssembler::fneg_d(FloatRegister Rd, FloatRegister Rs) { + fsgnjn_d(Rd, Rs, Rs); +} + +void MacroAssembler::vmnot_m(VectorRegister vd, VectorRegister vs) { + vmnand_mm(vd, vs, vs); +} + +void MacroAssembler::vncvt_x_x_w(VectorRegister vd, VectorRegister vs, VectorMask vm) { + vnsrl_wx(vd, vs, x0, vm); +} + +void MacroAssembler::vfneg_v(VectorRegister vd, VectorRegister vs) { + vfsgnjn_vv(vd, vs, vs); +} + +void MacroAssembler::la(Register Rd, const address &dest) { + int64_t offset = dest - pc(); + if (is_offset_in_range(offset, 32)) { + auipc(Rd, (int32_t)offset + 0x800); //0x800, Note:the 11th sign bit + addi(Rd, Rd, ((int64_t)offset << 52) >> 52); + } else { + movptr(Rd, dest); + } +} + +void MacroAssembler::la(Register Rd, const Address &adr) { + InstructionMark im(this); + code_section()->relocate(inst_mark(), adr.rspec()); + relocInfo::relocType rtype = adr.rspec().reloc()->type(); + + switch (adr.getMode()) { + case Address::literal: { + if (rtype == relocInfo::none) { + li(Rd, (intptr_t)(adr.target())); + } else { + movptr(Rd, adr.target()); + } + break; + } + case Address::base_plus_offset: { + int32_t offset = 0; + baseOffset(Rd, adr, offset); + addi(Rd, Rd, offset); + break; + } + default: + ShouldNotReachHere(); + } +} + +void MacroAssembler::la(Register Rd, Label &label) { + la(Rd, target(label)); +} + +#define INSN(NAME) \ + void MacroAssembler::NAME##z(Register Rs, const address &dest) { \ + NAME(Rs, zr, dest); \ + } \ + void MacroAssembler::NAME##z(Register Rs, Label &l, bool is_far) { \ + NAME(Rs, zr, l, is_far); \ + } \ + + INSN(beq); + INSN(bne); + INSN(blt); + INSN(ble); + INSN(bge); + INSN(bgt); + +#undef INSN + +// Float compare branch instructions + +#define INSN(NAME, FLOATCMP, BRANCH) \ + void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ + FLOATCMP##_s(t0, Rs1, Rs2); \ + BRANCH(t0, l, is_far); \ + } \ + void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ + FLOATCMP##_d(t0, Rs1, Rs2); \ + BRANCH(t0, l, is_far); \ + } + + INSN(beq, feq, bnez); + INSN(bne, feq, beqz); + +#undef INSN + + +#define INSN(NAME, FLOATCMP1, FLOATCMP2) \ + void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, \ + bool is_far, bool is_unordered) { \ + if (is_unordered) { \ + /* jump if either source is NaN or condition is expected */ \ + FLOATCMP2##_s(t0, Rs2, Rs1); \ + beqz(t0, l, is_far); \ + } else { \ + /* jump if no NaN in source and condition is expected */ \ + FLOATCMP1##_s(t0, Rs1, Rs2); \ + bnez(t0, l, is_far); \ + } \ + } \ + void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, \ + bool is_far, bool is_unordered) { \ + if (is_unordered) { \ + /* jump if either source is NaN or condition is expected */ \ + FLOATCMP2##_d(t0, Rs2, Rs1); \ + beqz(t0, l, is_far); \ + } else { \ + /* jump if no NaN in source and condition is expected */ \ + FLOATCMP1##_d(t0, Rs1, Rs2); \ + bnez(t0, l, is_far); \ + } \ + } + + INSN(ble, fle, flt); + INSN(blt, flt, fle); + +#undef INSN + +#define INSN(NAME, CMP) \ + void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, \ + bool is_far, bool is_unordered) { \ + float_##CMP(Rs2, Rs1, l, is_far, is_unordered); \ + } \ + void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, \ + bool is_far, bool is_unordered) { \ + double_##CMP(Rs2, Rs1, l, is_far, is_unordered); \ + } + + INSN(bgt, blt); + INSN(bge, ble); + +#undef INSN + + +#define INSN(NAME, CSR) \ + void MacroAssembler::NAME(Register Rd) { \ + csrr(Rd, CSR); \ + } + + INSN(rdinstret, CSR_INSTERT); + INSN(rdcycle, CSR_CYCLE); + INSN(rdtime, CSR_TIME); + INSN(frcsr, CSR_FCSR); + INSN(frrm, CSR_FRM); + INSN(frflags, CSR_FFLAGS); + +#undef INSN + +void MacroAssembler::csrr(Register Rd, unsigned csr) { + csrrs(Rd, csr, x0); +} + +#define INSN(NAME, OPFUN) \ + void MacroAssembler::NAME(unsigned csr, Register Rs) { \ + OPFUN(x0, csr, Rs); \ + } + + INSN(csrw, csrrw); + INSN(csrs, csrrs); + INSN(csrc, csrrc); + +#undef INSN + +#define INSN(NAME, OPFUN) \ + void MacroAssembler::NAME(unsigned csr, unsigned imm) { \ + OPFUN(x0, csr, imm); \ + } + + INSN(csrwi, csrrwi); + INSN(csrsi, csrrsi); + INSN(csrci, csrrci); + +#undef INSN + +#define INSN(NAME, CSR) \ + void MacroAssembler::NAME(Register Rd, Register Rs) { \ + csrrw(Rd, CSR, Rs); \ + } + + INSN(fscsr, CSR_FCSR); + INSN(fsrm, CSR_FRM); + INSN(fsflags, CSR_FFLAGS); + +#undef INSN + +#define INSN(NAME) \ + void MacroAssembler::NAME(Register Rs) { \ + NAME(x0, Rs); \ + } + + INSN(fscsr); + INSN(fsrm); + INSN(fsflags); + +#undef INSN + +void MacroAssembler::fsrmi(Register Rd, unsigned imm) { + guarantee(imm < 5, "Rounding Mode is invalid in Rounding Mode register"); + csrrwi(Rd, CSR_FRM, imm); +} + +void MacroAssembler::fsflagsi(Register Rd, unsigned imm) { + csrrwi(Rd, CSR_FFLAGS, imm); +} + +#define INSN(NAME) \ + void MacroAssembler::NAME(unsigned imm) { \ + NAME(x0, imm); \ + } + + INSN(fsrmi); + INSN(fsflagsi); + +#undef INSN + +void MacroAssembler::push_reg(Register Rs) +{ + addi(esp, esp, 0 - wordSize); + sd(Rs, Address(esp, 0)); +} + +void MacroAssembler::pop_reg(Register Rd) +{ + ld(Rd, esp, 0); + addi(esp, esp, wordSize); +} + +int MacroAssembler::bitset_to_regs(unsigned int bitset, unsigned char* regs) { + int count = 0; + // Scan bitset to accumulate register pairs + for (int reg = 31; reg >= 0; reg--) { + if ((1U << 31) & bitset) { + regs[count++] = reg; + } + bitset <<= 1; + } + return count; +} + +// Push lots of registers in the bit set supplied. Don't push sp. +// Return the number of words pushed +int MacroAssembler::push_reg(unsigned int bitset, Register stack) { + DEBUG_ONLY(int words_pushed = 0;) + CompressibleRegion cr(this); + + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + // reserve one slot to align for odd count + int offset = is_even(count) ? 0 : wordSize; + + if (count) { + addi(stack, stack, - count * wordSize - offset); + } + for (int i = count - 1; i >= 0; i--) { + sd(as_Register(regs[i]), Address(stack, (count - 1 - i) * wordSize + offset)); + DEBUG_ONLY(words_pushed ++;) + } + + assert(words_pushed == count, "oops, pushed != count"); + + return count; +} + +int MacroAssembler::pop_reg(unsigned int bitset, Register stack) { + DEBUG_ONLY(int words_popped = 0;) + CompressibleRegion cr(this); + + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + // reserve one slot to align for odd count + int offset = is_even(count) ? 0 : wordSize; + + for (int i = count - 1; i >= 0; i--) { + ld(as_Register(regs[i]), Address(stack, (count - 1 - i) * wordSize + offset)); + DEBUG_ONLY(words_popped ++;) + } + + if (count) { + addi(stack, stack, count * wordSize + offset); + } + assert(words_popped == count, "oops, popped != count"); + + return count; +} + +// Push float registers in the bitset, except sp. +// Return the number of heapwords pushed. +int MacroAssembler::push_fp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); + int words_pushed = 0; + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + int push_slots = count + (count & 1); + + if (count) { + addi(stack, stack, -push_slots * wordSize); + } + + for (int i = count - 1; i >= 0; i--) { + fsd(as_FloatRegister(regs[i]), Address(stack, (push_slots - 1 - i) * wordSize)); + words_pushed++; + } + + assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count); + return count; +} + +int MacroAssembler::pop_fp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); + int words_popped = 0; + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + int pop_slots = count + (count & 1); + + for (int i = count - 1; i >= 0; i--) { + fld(as_FloatRegister(regs[i]), Address(stack, (pop_slots - 1 - i) * wordSize)); + words_popped++; + } + + if (count) { + addi(stack, stack, pop_slots * wordSize); + } + + assert(words_popped == count, "oops, popped(%d) != count(%d)", words_popped, count); + return count; +} + +#ifdef COMPILER2 +int MacroAssembler::push_vp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); + int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); + + // Scan bitset to accumulate register pairs + unsigned char regs[32]; + int count = 0; + for (int reg = 31; reg >= 0; reg--) { + if ((1U << 31) & bitset) { + regs[count++] = reg; + } + bitset <<= 1; + } + + for (int i = 0; i < count; i++) { + sub(stack, stack, vector_size_in_bytes); + vs1r_v(as_VectorRegister(regs[i]), stack); + } + + return count * vector_size_in_bytes / wordSize; +} + +int MacroAssembler::pop_vp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); + int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); + + // Scan bitset to accumulate register pairs + unsigned char regs[32]; + int count = 0; + for (int reg = 31; reg >= 0; reg--) { + if ((1U << 31) & bitset) { + regs[count++] = reg; + } + bitset <<= 1; + } + + for (int i = count - 1; i >= 0; i--) { + vl1r_v(as_VectorRegister(regs[i]), stack); + add(stack, stack, vector_size_in_bytes); + } + + return count * vector_size_in_bytes / wordSize; +} +#endif // COMPILER2 + +void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude) { + CompressibleRegion cr(this); + // Push integer registers x7, x10-x17, x28-x31. + push_reg(RegSet::of(x7) + RegSet::range(x10, x17) + RegSet::range(x28, x31) - exclude, sp); + + // Push float registers f0-f7, f10-f17, f28-f31. + addi(sp, sp, - wordSize * 20); + int offset = 0; + for (int i = 0; i < 32; i++) { + if (i <= f7->encoding() || i >= f28->encoding() || (i >= f10->encoding() && i <= f17->encoding())) { + fsd(as_FloatRegister(i), Address(sp, wordSize * (offset ++))); + } + } +} + +void MacroAssembler::pop_call_clobbered_registers_except(RegSet exclude) { + CompressibleRegion cr(this); + int offset = 0; + for (int i = 0; i < 32; i++) { + if (i <= f7->encoding() || i >= f28->encoding() || (i >= f10->encoding() && i <= f17->encoding())) { + fld(as_FloatRegister(i), Address(sp, wordSize * (offset ++))); + } + } + addi(sp, sp, wordSize * 20); + + pop_reg(RegSet::of(x7) + RegSet::range(x10, x17) + RegSet::range(x28, x31) - exclude, sp); +} + +// Push all the integer registers, except zr(x0) & sp(x2) & gp(x3) & tp(x4). +void MacroAssembler::pusha() { + CompressibleRegion cr(this); + push_reg(0xffffffe2, sp); +} + +// Pop all the integer registers, except zr(x0) & sp(x2) & gp(x3) & tp(x4). +void MacroAssembler::popa() { + CompressibleRegion cr(this); + pop_reg(0xffffffe2, sp); +} + +void MacroAssembler::push_CPU_state(bool save_vectors, int vector_size_in_bytes) { + CompressibleRegion cr(this); + // integer registers, except zr(x0) & ra(x1) & sp(x2) & gp(x3) & tp(x4) + push_reg(0xffffffe0, sp); + + // float registers + addi(sp, sp, - 32 * wordSize); + for (int i = 0; i < 32; i++) { + fsd(as_FloatRegister(i), Address(sp, i * wordSize)); + } + + // vector registers + if (save_vectors) { + sub(sp, sp, vector_size_in_bytes * VectorRegisterImpl::number_of_registers); + vsetvli(t0, x0, Assembler::e64, Assembler::m8); + for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { + add(t0, sp, vector_size_in_bytes * i); + vse64_v(as_VectorRegister(i), t0); + } + } +} + +void MacroAssembler::pop_CPU_state(bool restore_vectors, int vector_size_in_bytes) { + CompressibleRegion cr(this); + // vector registers + if (restore_vectors) { + vsetvli(t0, x0, Assembler::e64, Assembler::m8); + for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { + vle64_v(as_VectorRegister(i), sp); + add(sp, sp, vector_size_in_bytes * 8); + } + } + + // float registers + for (int i = 0; i < 32; i++) { + fld(as_FloatRegister(i), Address(sp, i * wordSize)); + } + addi(sp, sp, 32 * wordSize); + + // integer registers, except zr(x0) & ra(x1) & sp(x2) & gp(x3) & tp(x4) + pop_reg(0xffffffe0, sp); +} + +static int patch_offset_in_jal(address branch, int64_t offset) { + assert(is_imm_in_range(offset, 20, 1), "offset is too large to be patched in one jal insrusction!\n"); + Assembler::patch(branch, 31, 31, (offset >> 20) & 0x1); // offset[20] ==> branch[31] + Assembler::patch(branch, 30, 21, (offset >> 1) & 0x3ff); // offset[10:1] ==> branch[30:21] + Assembler::patch(branch, 20, 20, (offset >> 11) & 0x1); // offset[11] ==> branch[20] + Assembler::patch(branch, 19, 12, (offset >> 12) & 0xff); // offset[19:12] ==> branch[19:12] + return NativeInstruction::instruction_size; // only one instruction +} + +static int patch_offset_in_conditional_branch(address branch, int64_t offset) { + assert(is_imm_in_range(offset, 12, 1), "offset is too large to be patched in one beq/bge/bgeu/blt/bltu/bne insrusction!\n"); + Assembler::patch(branch, 31, 31, (offset >> 12) & 0x1); // offset[12] ==> branch[31] + Assembler::patch(branch, 30, 25, (offset >> 5) & 0x3f); // offset[10:5] ==> branch[30:25] + Assembler::patch(branch, 7, 7, (offset >> 11) & 0x1); // offset[11] ==> branch[7] + Assembler::patch(branch, 11, 8, (offset >> 1) & 0xf); // offset[4:1] ==> branch[11:8] + return NativeInstruction::instruction_size; // only one instruction +} + +static int patch_offset_in_pc_relative(address branch, int64_t offset) { + const int PC_RELATIVE_INSTRUCTION_NUM = 2; // auipc, addi/jalr/load + Assembler::patch(branch, 31, 12, ((offset + 0x800) >> 12) & 0xfffff); // Auipc. offset[31:12] ==> branch[31:12] + Assembler::patch(branch + 4, 31, 20, offset & 0xfff); // Addi/Jalr/Load. offset[11:0] ==> branch[31:20] + return PC_RELATIVE_INSTRUCTION_NUM * NativeInstruction::instruction_size; +} + +static int patch_addr_in_movptr(address branch, address target) { + const int MOVPTR_INSTRUCTIONS_NUM = 6; // lui + addi + slli + addi + slli + addi/jalr/load + int32_t lower = ((intptr_t)target << 36) >> 36; + int64_t upper = ((intptr_t)target - lower) >> 28; + Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[47:28] + target[27] ==> branch[31:12] + Assembler::patch(branch + 4, 31, 20, (lower >> 16) & 0xfff); // Addi. target[27:16] ==> branch[31:20] + Assembler::patch(branch + 12, 31, 20, (lower >> 5) & 0x7ff); // Addi. target[15: 5] ==> branch[31:20] + Assembler::patch(branch + 20, 31, 20, lower & 0x1f); // Addi/Jalr/Load. target[ 4: 0] ==> branch[31:20] + return MOVPTR_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; +} + +static int patch_imm_in_li64(address branch, address target) { + const int LI64_INSTRUCTIONS_NUM = 8; // lui + addi + slli + addi + slli + addi + slli + addi + int64_t lower = (intptr_t)target & 0xffffffff; + lower = lower - ((lower << 44) >> 44); + int64_t tmp_imm = ((uint64_t)((intptr_t)target & 0xffffffff00000000)) + (uint64_t)lower; + int32_t upper = (tmp_imm - (int32_t)lower) >> 32; + int64_t tmp_upper = upper, tmp_lower = upper; + tmp_lower = (tmp_lower << 52) >> 52; + tmp_upper -= tmp_lower; + tmp_upper >>= 12; + // Load upper 32 bits. Upper = target[63:32], but if target[31] = 1 or (target[31:28] == 0x7ff && target[19] == 1), + // upper = target[63:32] + 1. + Assembler::patch(branch + 0, 31, 12, tmp_upper & 0xfffff); // Lui. + Assembler::patch(branch + 4, 31, 20, tmp_lower & 0xfff); // Addi. + // Load the rest 32 bits. + Assembler::patch(branch + 12, 31, 20, ((int32_t)lower >> 20) & 0xfff); // Addi. + Assembler::patch(branch + 20, 31, 20, (((intptr_t)target << 44) >> 52) & 0xfff); // Addi. + Assembler::patch(branch + 28, 31, 20, (intptr_t)target & 0xff); // Addi. + return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; +} + +static int patch_imm_in_li32(address branch, int32_t target) { + const int LI32_INSTRUCTIONS_NUM = 2; // lui + addiw + int64_t upper = (intptr_t)target; + int32_t lower = (((int32_t)target) << 20) >> 20; + upper -= lower; + upper = (int32_t)upper; + Assembler::patch(branch + 0, 31, 12, (upper >> 12) & 0xfffff); // Lui. + Assembler::patch(branch + 4, 31, 20, lower & 0xfff); // Addiw. + return LI32_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; +} + +static long get_offset_of_jal(address insn_addr) { + assert_cond(insn_addr != NULL); + long offset = 0; + unsigned insn = *(unsigned*)insn_addr; + long val = (long)Assembler::sextract(insn, 31, 12); + offset |= ((val >> 19) & 0x1) << 20; + offset |= (val & 0xff) << 12; + offset |= ((val >> 8) & 0x1) << 11; + offset |= ((val >> 9) & 0x3ff) << 1; + offset = (offset << 43) >> 43; + return offset; +} + +static long get_offset_of_conditional_branch(address insn_addr) { + long offset = 0; + assert_cond(insn_addr != NULL); + unsigned insn = *(unsigned*)insn_addr; + offset = (long)Assembler::sextract(insn, 31, 31); + offset = (offset << 12) | (((long)(Assembler::sextract(insn, 7, 7) & 0x1)) << 11); + offset = offset | (((long)(Assembler::sextract(insn, 30, 25) & 0x3f)) << 5); + offset = offset | (((long)(Assembler::sextract(insn, 11, 8) & 0xf)) << 1); + offset = (offset << 41) >> 41; + return offset; +} + +static long get_offset_of_pc_relative(address insn_addr) { + long offset = 0; + assert_cond(insn_addr != NULL); + offset = ((long)(Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12))) << 12; // Auipc. + offset += ((long)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)); // Addi/Jalr/Load. + offset = (offset << 32) >> 32; + return offset; +} + +static address get_target_of_movptr(address insn_addr) { + assert_cond(insn_addr != NULL); + intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 28; // Lui. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 16; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 5; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[5], 31, 20)); // Addi/Jalr/Load. + return (address) target_address; +} + +static address get_target_of_li64(address insn_addr) { + assert_cond(insn_addr != NULL); + intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 44; // Lui. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 32; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 20; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[5], 31, 20)) << 8; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[7], 31, 20)); // Addi. + return (address)target_address; +} + +static address get_target_of_li32(address insn_addr) { + assert_cond(insn_addr != NULL); + intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 12; // Lui. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)); // Addiw. + return (address)target_address; +} + +// Patch any kind of instruction; there may be several instructions. +// Return the total length (in bytes) of the instructions. +int MacroAssembler::pd_patch_instruction_size(address branch, address target) { + assert_cond(branch != NULL); + int64_t offset = target - branch; + if (NativeInstruction::is_jal_at(branch)) { // jal + return patch_offset_in_jal(branch, offset); + } else if (NativeInstruction::is_branch_at(branch)) { // beq/bge/bgeu/blt/bltu/bne + return patch_offset_in_conditional_branch(branch, offset); + } else if (NativeInstruction::is_pc_relative_at(branch)) { // auipc, addi/jalr/load + return patch_offset_in_pc_relative(branch, offset); + } else if (NativeInstruction::is_movptr_at(branch)) { // movptr + return patch_addr_in_movptr(branch, target); + } else if (NativeInstruction::is_li64_at(branch)) { // li64 + return patch_imm_in_li64(branch, target); + } else if (NativeInstruction::is_li32_at(branch)) { // li32 + int64_t imm = (intptr_t)target; + return patch_imm_in_li32(branch, (int32_t)imm); + } else { +#ifdef ASSERT + tty->print_cr("pd_patch_instruction_size: instruction 0x%x at " INTPTR_FORMAT " could not be patched!\n", + *(unsigned*)branch, p2i(branch)); + Disassembler::decode(branch - 16, branch + 16); +#endif + ShouldNotReachHere(); + return -1; + } +} + +address MacroAssembler::target_addr_for_insn(address insn_addr) { + long offset = 0; + assert_cond(insn_addr != NULL); + if (NativeInstruction::is_jal_at(insn_addr)) { // jal + offset = get_offset_of_jal(insn_addr); + } else if (NativeInstruction::is_branch_at(insn_addr)) { // beq/bge/bgeu/blt/bltu/bne + offset = get_offset_of_conditional_branch(insn_addr); + } else if (NativeInstruction::is_pc_relative_at(insn_addr)) { // auipc, addi/jalr/load + offset = get_offset_of_pc_relative(insn_addr); + } else if (NativeInstruction::is_movptr_at(insn_addr)) { // movptr + return get_target_of_movptr(insn_addr); + } else if (NativeInstruction::is_li64_at(insn_addr)) { // li64 + return get_target_of_li64(insn_addr); + } else if (NativeInstruction::is_li32_at(insn_addr)) { // li32 + return get_target_of_li32(insn_addr); + } else { + ShouldNotReachHere(); + } + return address(((uintptr_t)insn_addr + offset)); +} + +int MacroAssembler::patch_oop(address insn_addr, address o) { + // OOPs are either narrow (32 bits) or wide (48 bits). We encode + // narrow OOPs by setting the upper 16 bits in the first + // instruction. + if (NativeInstruction::is_li32_at(insn_addr)) { + // Move narrow OOP + uint32_t n = CompressedOops::narrow_oop_value(cast_to_oop(o)); + return patch_imm_in_li32(insn_addr, (int32_t)n); + } else if (NativeInstruction::is_movptr_at(insn_addr)) { + // Move wide OOP + return patch_addr_in_movptr(insn_addr, o); + } + ShouldNotReachHere(); + return -1; +} + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops) { + if (Universe::is_fully_initialized()) { + mv(xheapbase, CompressedOops::ptrs_base()); + } else { + int32_t offset = 0; + la_patchable(xheapbase, ExternalAddress((address)CompressedOops::ptrs_base_addr()), offset); + ld(xheapbase, Address(xheapbase, offset)); + } + } +} + +void MacroAssembler::mv(Register Rd, Address dest) { + assert(dest.getMode() == Address::literal, "Address mode should be Address::literal"); + code_section()->relocate(pc(), dest.rspec()); + movptr(Rd, dest.target()); +} + +void MacroAssembler::mv(Register Rd, address addr) { + // Here in case of use with relocation, use fix length instruciton + // movptr instead of li + movptr(Rd, addr); +} + +void MacroAssembler::mv(Register Rd, RegisterOrConstant src) { + if (src.is_register()) { + mv(Rd, src.as_register()); + } else { + mv(Rd, src.as_constant()); + } +} + +void MacroAssembler::andrw(Register Rd, Register Rs1, Register Rs2) { + andr(Rd, Rs1, Rs2); + // addw: The result is clipped to 32 bits, then the sign bit is extended, + // and the result is stored in Rd + addw(Rd, Rd, zr); +} + +void MacroAssembler::orrw(Register Rd, Register Rs1, Register Rs2) { + orr(Rd, Rs1, Rs2); + // addw: The result is clipped to 32 bits, then the sign bit is extended, + // and the result is stored in Rd + addw(Rd, Rd, zr); +} + +void MacroAssembler::xorrw(Register Rd, Register Rs1, Register Rs2) { + xorr(Rd, Rs1, Rs2); + // addw: The result is clipped to 32 bits, then the sign bit is extended, + // and the result is stored in Rd + addw(Rd, Rd, zr); +} + +// Note: load_unsigned_short used to be called load_unsigned_word. +int MacroAssembler::load_unsigned_short(Register dst, Address src) { + int off = offset(); + lhu(dst, src); + return off; +} + +int MacroAssembler::load_unsigned_byte(Register dst, Address src) { + int off = offset(); + lbu(dst, src); + return off; +} + +int MacroAssembler::load_signed_short(Register dst, Address src) { + int off = offset(); + lh(dst, src); + return off; +} + +int MacroAssembler::load_signed_byte(Register dst, Address src) { + int off = offset(); + lb(dst, src); + return off; +} + +void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2) { + switch (size_in_bytes) { + case 8: ld(dst, src); break; + case 4: is_signed ? lw(dst, src) : lwu(dst, src); break; + case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; + case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2) { + switch (size_in_bytes) { + case 8: sd(src, dst); break; + case 4: sw(src, dst); break; + case 2: sh(src, dst); break; + case 1: sb(src, dst); break; + default: ShouldNotReachHere(); + } +} + +// reverse bytes in halfword in lower 16 bits and sign-extend +// Rd[15:0] = Rs[7:0] Rs[15:8] (sign-extend to 64 bits) +void MacroAssembler::revb_h_h(Register Rd, Register Rs, Register tmp) { + if (UseZbb) { + rev8(Rd, Rs); + srai(Rd, Rd, 48); + return; + } + assert_different_registers(Rs, tmp); + assert_different_registers(Rd, tmp); + srli(tmp, Rs, 8); + andi(tmp, tmp, 0xFF); + slli(Rd, Rs, 56); + srai(Rd, Rd, 48); // sign-extend + orr(Rd, Rd, tmp); +} + +// reverse bytes in lower word and sign-extend +// Rd[31:0] = Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] (sign-extend to 64 bits) +void MacroAssembler::revb_w_w(Register Rd, Register Rs, Register tmp1, Register tmp2) { + if (UseZbb) { + rev8(Rd, Rs); + srai(Rd, Rd, 32); + return; + } + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1, tmp2); + revb_h_w_u(Rd, Rs, tmp1, tmp2); + slli(tmp2, Rd, 48); + srai(tmp2, tmp2, 32); // sign-extend + srli(Rd, Rd, 16); + orr(Rd, Rd, tmp2); +} + +// reverse bytes in halfword in lower 16 bits and zero-extend +// Rd[15:0] = Rs[7:0] Rs[15:8] (zero-extend to 64 bits) +void MacroAssembler::revb_h_h_u(Register Rd, Register Rs, Register tmp) { + if (UseZbb) { + rev8(Rd, Rs); + srli(Rd, Rd, 48); + return; + } + assert_different_registers(Rs, tmp); + assert_different_registers(Rd, tmp); + srli(tmp, Rs, 8); + andi(tmp, tmp, 0xFF); + andi(Rd, Rs, 0xFF); + slli(Rd, Rd, 8); + orr(Rd, Rd, tmp); +} + +// reverse bytes in halfwords in lower 32 bits and zero-extend +// Rd[31:0] = Rs[23:16] Rs[31:24] Rs[7:0] Rs[15:8] (zero-extend to 64 bits) +void MacroAssembler::revb_h_w_u(Register Rd, Register Rs, Register tmp1, Register tmp2) { + if (UseZbb) { + rev8(Rd, Rs); + rori(Rd, Rd, 32); + roriw(Rd, Rd, 16); + zero_extend(Rd, Rd, 32); + return; + } + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1, tmp2); + srli(tmp2, Rs, 16); + revb_h_h_u(tmp2, tmp2, tmp1); + revb_h_h_u(Rd, Rs, tmp1); + slli(tmp2, tmp2, 16); + orr(Rd, Rd, tmp2); +} + +// This method is only used for revb_h +// Rd = Rs[47:0] Rs[55:48] Rs[63:56] +void MacroAssembler::revb_h_helper(Register Rd, Register Rs, Register tmp1, Register tmp2) { + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1); + srli(tmp1, Rs, 48); + andi(tmp2, tmp1, 0xFF); + slli(tmp2, tmp2, 8); + srli(tmp1, tmp1, 8); + orr(tmp1, tmp1, tmp2); + slli(Rd, Rs, 16); + orr(Rd, Rd, tmp1); +} + +// reverse bytes in each halfword +// Rd[63:0] = Rs[55:48] Rs[63:56] Rs[39:32] Rs[47:40] Rs[23:16] Rs[31:24] Rs[7:0] Rs[15:8] +void MacroAssembler::revb_h(Register Rd, Register Rs, Register tmp1, Register tmp2) { + if (UseZbb) { + assert_different_registers(Rs, tmp1); + assert_different_registers(Rd, tmp1); + rev8(Rd, Rs); + zero_extend(tmp1, Rd, 32); + roriw(tmp1, tmp1, 16); + slli(tmp1, tmp1, 32); + srli(Rd, Rd, 32); + roriw(Rd, Rd, 16); + zero_extend(Rd, Rd, 32); + orr(Rd, Rd, tmp1); + return; + } + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1, tmp2); + revb_h_helper(Rd, Rs, tmp1, tmp2); + for (int i = 0; i < 3; ++i) { + revb_h_helper(Rd, Rd, tmp1, tmp2); + } +} + +// reverse bytes in each word +// Rd[63:0] = Rs[39:32] Rs[47:40] Rs[55:48] Rs[63:56] Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] +void MacroAssembler::revb_w(Register Rd, Register Rs, Register tmp1, Register tmp2) { + if (UseZbb) { + rev8(Rd, Rs); + rori(Rd, Rd, 32); + return; + } + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1, tmp2); + revb(Rd, Rs, tmp1, tmp2); + ror_imm(Rd, Rd, 32); +} + +// reverse bytes in doubleword +// Rd[63:0] = Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] Rs[39:32] Rs[47,40] Rs[55,48] Rs[63:56] +void MacroAssembler::revb(Register Rd, Register Rs, Register tmp1, Register tmp2) { + if (UseZbb) { + rev8(Rd, Rs); + return; + } + assert_different_registers(Rs, tmp1, tmp2); + assert_different_registers(Rd, tmp1, tmp2); + andi(tmp1, Rs, 0xFF); + slli(tmp1, tmp1, 8); + for (int step = 8; step < 56; step += 8) { + srli(tmp2, Rs, step); + andi(tmp2, tmp2, 0xFF); + orr(tmp1, tmp1, tmp2); + slli(tmp1, tmp1, 8); + } + srli(Rd, Rs, 56); + andi(Rd, Rd, 0xFF); + orr(Rd, tmp1, Rd); +} + +// rotate right with shift bits +void MacroAssembler::ror_imm(Register dst, Register src, uint32_t shift, Register tmp) +{ + if (UseZbb) { + rori(dst, src, shift); + return; + } + + assert_different_registers(dst, tmp); + assert_different_registers(src, tmp); + assert(shift < 64, "shift amount must be < 64"); + slli(tmp, src, 64 - shift); + srli(dst, src, shift); + orr(dst, dst, tmp); +} + +void MacroAssembler::andi(Register Rd, Register Rn, int64_t imm, Register tmp) { + if (is_imm_in_range(imm, 12, 0)) { + and_imm12(Rd, Rn, imm); + } else { + assert_different_registers(Rn, tmp); + li(tmp, imm); + andr(Rd, Rn, tmp); + } +} + +void MacroAssembler::orptr(Address adr, RegisterOrConstant src, Register tmp1, Register tmp2) { + ld(tmp1, adr); + if (src.is_register()) { + orr(tmp1, tmp1, src.as_register()); + } else { + if (is_imm_in_range(src.as_constant(), 12, 0)) { + ori(tmp1, tmp1, src.as_constant()); + } else { + assert_different_registers(tmp1, tmp2); + li(tmp2, src.as_constant()); + orr(tmp1, tmp1, tmp2); + } + } + sd(tmp1, adr); +} + +void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp, Label &L) { + if (UseCompressedClassPointers) { + lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); + if (CompressedKlassPointers::base() == NULL) { + slli(tmp, tmp, CompressedKlassPointers::shift()); + beq(trial_klass, tmp, L); + return; + } + decode_klass_not_null(tmp); + } else { + ld(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); + } + beq(trial_klass, tmp, L); +} + +// Move an oop into a register. immediate is true if we want +// immediate instructions and nmethod entry barriers are not enabled. +// i.e. we are not going to patch this instruction while the code is being +// executed by another thread. +void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) { + int oop_index; + if (obj == NULL) { + oop_index = oop_recorder()->allocate_oop_index(obj); + } else { +#ifdef ASSERT + { + ThreadInVMfromUnknown tiv; + assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); + } +#endif + oop_index = oop_recorder()->find_index(obj); + } + RelocationHolder rspec = oop_Relocation::spec(oop_index); + + // nmethod entry barrier necessitate using the constant pool. They have to be + // ordered with respected to oop access. + // Using immediate literals would necessitate fence.i. + if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate) { + address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address + ld_constant(dst, Address(dummy, rspec)); + } else + mv(dst, Address((address)obj, rspec)); +} + +// Move a metadata address into a register. +void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { + int oop_index; + if (obj == NULL) { + oop_index = oop_recorder()->allocate_metadata_index(obj); + } else { + oop_index = oop_recorder()->find_index(obj); + } + RelocationHolder rspec = metadata_Relocation::spec(oop_index); + mv(dst, Address((address)obj, rspec)); +} + +// Writes to stack successive pages until offset reached to check for +// stack overflow + shadow pages. This clobbers tmp. +void MacroAssembler::bang_stack_size(Register size, Register tmp) { + assert_different_registers(tmp, size, t0); + // Bang stack for total size given plus shadow page size. + // Bang one page at a time because large size can bang beyond yellow and + // red zones. + mv(t0, os::vm_page_size()); + Label loop; + bind(loop); + sub(tmp, sp, t0); + subw(size, size, t0); + sd(size, Address(tmp)); + bgtz(size, loop); + + // Bang down shadow pages too. + // At this point, (tmp-0) is the last address touched, so don't + // touch it again. (It was touched as (tmp-pagesize) but then tmp + // was post-decremented.) Skip this address by starting at i=1, and + // touch a few more pages below. N.B. It is important to touch all + // the way down to and including i=StackShadowPages. + for (int i = 0; i < (int)(StackOverflow::stack_shadow_zone_size() / os::vm_page_size()) - 1; i++) { + // this could be any sized move but this is can be a debugging crumb + // so the bigger the better. + sub(tmp, tmp, os::vm_page_size()); + sd(size, Address(tmp, 0)); + } +} + +SkipIfEqual::SkipIfEqual(MacroAssembler* masm, const bool* flag_addr, bool value) { + assert_cond(masm != NULL); + int32_t offset = 0; + _masm = masm; + _masm->la_patchable(t0, ExternalAddress((address)flag_addr), offset); + _masm->lbu(t0, Address(t0, offset)); + _masm->beqz(t0, _label); +} + +SkipIfEqual::~SkipIfEqual() { + assert_cond(_masm != NULL); + _masm->bind(_label); + _masm = NULL; +} + +void MacroAssembler::load_mirror(Register dst, Register method, Register tmp) { + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + ld(dst, Address(xmethod, Method::const_offset())); + ld(dst, Address(dst, ConstMethod::constants_offset())); + ld(dst, Address(dst, ConstantPool::pool_holder_offset_in_bytes())); + ld(dst, Address(dst, mirror_offset)); + resolve_oop_handle(dst, tmp); +} + +void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { + // OopHandle::resolve is an indirection. + assert_different_registers(result, tmp); + access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, noreg); +} + +// ((WeakHandle)result).resolve() +void MacroAssembler::resolve_weak_handle(Register result, Register tmp) { + assert_different_registers(result, tmp); + Label resolved; + + // A null weak handle resolves to null. + beqz(result, resolved); + + // Only 64 bit platforms support GCs that require a tmp register + // Only IN_HEAP loads require a thread_tmp register + // WeakHandle::resolve is an indirection like jweak. + access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, + result, Address(result), tmp, noreg /* tmp_thread */); + bind(resolved); +} + +void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, + Register dst, Address src, + Register tmp1, Register thread_tmp) { + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); + bool as_raw = (decorators & AS_RAW) != 0; + if (as_raw) { + bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); + } else { + bs->load_at(this, decorators, type, dst, src, tmp1, thread_tmp); + } +} + +void MacroAssembler::null_check(Register reg, int offset) { + if (needs_explicit_null_check(offset)) { + // provoke OS NULL exception if reg = NULL by + // accessing M[reg] w/o changing any registers + // NOTE: this is plenty to provoke a segv + ld(zr, Address(reg, 0)); + } else { + // nothing to do, (later) access of M[reg + offset] + // will provoke OS NULL exception if reg = NULL + } +} + +void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, + Address dst, Register src, + Register tmp1, Register thread_tmp) { + 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, thread_tmp); + } else { + bs->store_at(this, decorators, type, dst, src, tmp1, thread_tmp); + } +} + +// Algorithm must match CompressedOops::encode. +void MacroAssembler::encode_heap_oop(Register d, Register s) { + verify_oop(s, "broken oop in encode_heap_oop"); + if (CompressedOops::base() == NULL) { + if (CompressedOops::shift() != 0) { + assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); + srli(d, s, LogMinObjAlignmentInBytes); + } else { + mv(d, s); + } + } else { + Label notNull; + sub(d, s, xheapbase); + bgez(d, notNull); + mv(d, zr); + bind(notNull); + if (CompressedOops::shift() != 0) { + assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); + srli(d, d, CompressedOops::shift()); + } + } +} + +void MacroAssembler::load_klass(Register dst, Register src) { + if (UseCompressedClassPointers) { + lwu(dst, Address(src, oopDesc::klass_offset_in_bytes())); + decode_klass_not_null(dst); + } else { + ld(dst, Address(src, oopDesc::klass_offset_in_bytes())); + } +} + +void MacroAssembler::store_klass(Register dst, Register src) { + // FIXME: Should this be a store release? concurrent gcs assumes + // klass length is valid if klass field is not null. + if (UseCompressedClassPointers) { + encode_klass_not_null(src); + sw(src, Address(dst, oopDesc::klass_offset_in_bytes())); + } else { + sd(src, Address(dst, oopDesc::klass_offset_in_bytes())); + } +} + +void MacroAssembler::store_klass_gap(Register dst, Register src) { + if (UseCompressedClassPointers) { + // Store to klass gap in destination + sw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes())); + } +} + +void MacroAssembler::decode_klass_not_null(Register r) { + decode_klass_not_null(r, r); +} + +void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) { + assert(UseCompressedClassPointers, "should only be used for compressed headers"); + + if (CompressedKlassPointers::base() == NULL) { + if (CompressedKlassPointers::shift() != 0) { + assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); + slli(dst, src, LogKlassAlignmentInBytes); + } else { + mv(dst, src); + } + return; + } + + Register xbase = dst; + if (dst == src) { + xbase = tmp; + } + + assert_different_registers(src, xbase); + li(xbase, (uintptr_t)CompressedKlassPointers::base()); + + if (CompressedKlassPointers::shift() != 0) { + assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); + assert_different_registers(t0, xbase); + shadd(dst, src, xbase, t0, LogKlassAlignmentInBytes); + } else { + add(dst, xbase, src); + } + + if (xbase == xheapbase) { reinit_heapbase(); } +} + +void MacroAssembler::encode_klass_not_null(Register r) { + encode_klass_not_null(r, r); +} + +void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) { + assert(UseCompressedClassPointers, "should only be used for compressed headers"); + + if (CompressedKlassPointers::base() == NULL) { + if (CompressedKlassPointers::shift() != 0) { + assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); + srli(dst, src, LogKlassAlignmentInBytes); + } else { + mv(dst, src); + } + return; + } + + if (((uint64_t)(uintptr_t)CompressedKlassPointers::base() & 0xffffffff) == 0 && + CompressedKlassPointers::shift() == 0) { + zero_extend(dst, src, 32); + return; + } + + Register xbase = dst; + if (dst == src) { + xbase = tmp; + } + + assert_different_registers(src, xbase); + li(xbase, (intptr_t)CompressedKlassPointers::base()); + sub(dst, src, xbase); + if (CompressedKlassPointers::shift() != 0) { + assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); + srli(dst, dst, LogKlassAlignmentInBytes); + } + if (xbase == xheapbase) { + reinit_heapbase(); + } +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + decode_heap_oop_not_null(r, r); +} + +void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { + assert(UseCompressedOops, "should only be used for compressed headers"); + assert(Universe::heap() != NULL, "java heap should be initialized"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + if (CompressedOops::shift() != 0) { + assert(LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); + slli(dst, src, LogMinObjAlignmentInBytes); + if (CompressedOops::base() != NULL) { + add(dst, xheapbase, dst); + } + } else { + assert(CompressedOops::base() == NULL, "sanity"); + mv(dst, src); + } +} + +void MacroAssembler::decode_heap_oop(Register d, Register s) { + if (CompressedOops::base() == NULL) { + if (CompressedOops::shift() != 0 || d != s) { + slli(d, s, CompressedOops::shift()); + } + } else { + Label done; + mv(d, s); + beqz(s, done); + shadd(d, s, xheapbase, d, LogMinObjAlignmentInBytes); + bind(done); + } + verify_oop(d, "broken oop in decode_heap_oop"); +} + +void MacroAssembler::store_heap_oop(Address dst, Register src, Register tmp1, + Register thread_tmp, DecoratorSet decorators) { + access_store_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, thread_tmp); +} + +void MacroAssembler::load_heap_oop(Register dst, Address src, Register tmp1, + Register thread_tmp, DecoratorSet decorators) { + access_load_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, thread_tmp); +} + +void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1, + Register thread_tmp, DecoratorSet decorators) { + access_load_at(T_OBJECT, IN_HEAP | IS_NOT_NULL, dst, src, tmp1, thread_tmp); +} + +// Used for storing NULLs. +void MacroAssembler::store_heap_oop_null(Address dst) { + access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg); +} + +int MacroAssembler::corrected_idivl(Register result, Register rs1, Register rs2, + bool want_remainder) +{ + // Full implementation of Java idiv and irem. The function + // returns the (pc) offset of the div instruction - may be needed + // for implicit exceptions. + // + // input : rs1: dividend + // rs2: divisor + // + // result: either + // quotient (= rs1 idiv rs2) + // remainder (= rs1 irem rs2) + + + int idivl_offset = offset(); + if (!want_remainder) { + divw(result, rs1, rs2); + } else { + remw(result, rs1, rs2); // result = rs1 % rs2; + } + return idivl_offset; +} + +int MacroAssembler::corrected_idivq(Register result, Register rs1, Register rs2, + bool want_remainder) +{ + // Full implementation of Java ldiv and lrem. The function + // returns the (pc) offset of the div instruction - may be needed + // for implicit exceptions. + // + // input : rs1: dividend + // rs2: divisor + // + // result: either + // quotient (= rs1 idiv rs2) + // remainder (= rs1 irem rs2) + + int idivq_offset = offset(); + if (!want_remainder) { + div(result, rs1, rs2); + } else { + rem(result, rs1, rs2); // result = rs1 % rs2; + } + return idivq_offset; +} + +// Look up the method for a megamorpic invkkeinterface call. +// The target method is determined by . +// The receiver klass is in recv_klass. +// On success, the result will be in method_result, and execution falls through. +// On failure, execution transfers to the given label. +void MacroAssembler::lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_tmp, + Label& L_no_such_interface, + bool return_method) { + assert_different_registers(recv_klass, intf_klass, scan_tmp); + assert_different_registers(method_result, intf_klass, scan_tmp); + assert(recv_klass != method_result || !return_method, + "recv_klass can be destroyed when mehtid isn't needed"); + assert(itable_index.is_constant() || itable_index.as_register() == method_result, + "caller must be same register for non-constant itable index as for method"); + + // Compute start of first itableOffsetEntry (which is at the end of the vtable). + int vtable_base = in_bytes(Klass::vtable_start_offset()); + int itentry_off = itableMethodEntry::method_offset_in_bytes(); + int scan_step = itableOffsetEntry::size() * wordSize; + int vte_size = vtableEntry::size_in_bytes(); + assert(vte_size == wordSize, "else adjust times_vte_scale"); + + lwu(scan_tmp, Address(recv_klass, Klass::vtable_length_offset())); + + // %%% Could store the aligned, prescaled offset in the klassoop. + shadd(scan_tmp, scan_tmp, recv_klass, scan_tmp, 3); + add(scan_tmp, scan_tmp, vtable_base); + + if (return_method) { + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + if (itable_index.is_register()) { + slli(t0, itable_index.as_register(), 3); + } else { + li(t0, itable_index.as_constant() << 3); + } + add(recv_klass, recv_klass, t0); + if (itentry_off) { + add(recv_klass, recv_klass, itentry_off); + } + } + + Label search, found_method; + + ld(method_result, Address(scan_tmp, itableOffsetEntry::interface_offset_in_bytes())); + beq(intf_klass, method_result, found_method); + bind(search); + // Check that the previous entry is non-null. A null entry means that + // the receiver class doens't implement the interface, and wasn't the + // same as when the caller was compiled. + beqz(method_result, L_no_such_interface, /* is_far */ true); + addi(scan_tmp, scan_tmp, scan_step); + ld(method_result, Address(scan_tmp, itableOffsetEntry::interface_offset_in_bytes())); + bne(intf_klass, method_result, search); + + bind(found_method); + + // Got a hit. + if (return_method) { + lwu(scan_tmp, Address(scan_tmp, itableOffsetEntry::offset_offset_in_bytes())); + add(method_result, recv_klass, scan_tmp); + ld(method_result, Address(method_result)); + } +} + +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + const int base = in_bytes(Klass::vtable_start_offset()); + assert(vtableEntry::size() * wordSize == 8, + "adjust the scaling in the code below"); + int vtable_offset_in_bytes = base + vtableEntry::method_offset_in_bytes(); + + if (vtable_index.is_register()) { + shadd(method_result, vtable_index.as_register(), recv_klass, method_result, LogBytesPerWord); + ld(method_result, Address(method_result, vtable_offset_in_bytes)); + } else { + vtable_offset_in_bytes += vtable_index.as_constant() * wordSize; + ld(method_result, form_address(method_result, recv_klass, vtable_offset_in_bytes)); + } +} + +void MacroAssembler::membar(uint32_t order_constraint) { + address prev = pc() - NativeMembar::instruction_size; + address last = code()->last_insn(); + + if (last != NULL && nativeInstruction_at(last)->is_membar() && prev == last) { + NativeMembar *bar = NativeMembar_at(prev); + // We are merging two memory barrier instructions. On RISCV we + // can do this simply by ORing them together. + bar->set_kind(bar->get_kind() | order_constraint); + BLOCK_COMMENT("merged membar"); + } else { + code()->set_last_insn(pc()); + + uint32_t predecessor = 0; + uint32_t successor = 0; + + membar_mask_to_pred_succ(order_constraint, predecessor, successor); + fence(predecessor, successor); + } +} + +// Form an addres from base + offset in Rd. Rd my or may not +// actually be used: you must use the Address that is returned. It +// is up to you to ensure that the shift provided mathces the size +// of your data. +Address MacroAssembler::form_address(Register Rd, Register base, long byte_offset) { + if (is_offset_in_range(byte_offset, 12)) { // 12: imm in range 2^12 + return Address(base, byte_offset); + } + + // Do it the hard way + mv(Rd, byte_offset); + add(Rd, base, Rd); + return Address(Rd); +} + +void MacroAssembler::check_klass_subtype(Register sub_klass, + Register super_klass, + Register tmp_reg, + Label& L_success) { + Label L_failure; + check_klass_subtype_fast_path(sub_klass, super_klass, tmp_reg, &L_success, &L_failure, NULL); + check_klass_subtype_slow_path(sub_klass, super_klass, tmp_reg, noreg, &L_success, NULL); + bind(L_failure); +} + +void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod) { + ld(t0, Address(xthread, JavaThread::polling_word_offset())); + if (acquire) { + membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + } + if (at_return) { + bgtu(in_nmethod ? sp : fp, t0, slow_path, true /* is_far */); + } else { + andi(t0, t0, SafepointMechanism::poll_bit()); + bnez(t0, slow_path, true /* is_far */); + } +} + +void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, + Label &succeed, Label *fail) { + // oldv holds comparison value + // newv holds value to write in exchange + // addr identifies memory word to compare against/update + Label retry_load, nope; + bind(retry_load); + // Load reserved from the memory location + lr_d(tmp, addr, Assembler::aqrl); + // Fail and exit if it is not what we expect + bne(tmp, oldv, nope); + // If the store conditional succeeds, tmp will be zero + sc_d(tmp, newv, addr, Assembler::rl); + beqz(tmp, succeed); + // Retry only when the store conditional failed + j(retry_load); + + bind(nope); + membar(AnyAny); + mv(oldv, tmp); + if (fail != NULL) { + j(*fail); + } +} + +void MacroAssembler::cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, + Label &succeed, Label *fail) { + assert(oopDesc::mark_offset_in_bytes() == 0, "assumption"); + cmpxchgptr(oldv, newv, obj, tmp, succeed, fail); +} + +void MacroAssembler::load_reserved(Register addr, + enum operand_size size, + Assembler::Aqrl acquire) { + switch (size) { + case int64: + lr_d(t0, addr, acquire); + break; + case int32: + lr_w(t0, addr, acquire); + break; + case uint32: + lr_w(t0, addr, acquire); + zero_extend(t0, t0, 32); + break; + default: + ShouldNotReachHere(); + } +} + +void MacroAssembler::store_conditional(Register addr, + Register new_val, + enum operand_size size, + Assembler::Aqrl release) { + switch (size) { + case int64: + sc_d(t0, new_val, addr, release); + break; + case int32: + case uint32: + sc_w(t0, new_val, addr, release); + break; + default: + ShouldNotReachHere(); + } +} + + +void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected, + Register new_val, + enum operand_size size, + Register tmp1, Register tmp2, Register tmp3) { + assert(size == int8 || size == int16, "unsupported operand size"); + + Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3; + + andi(shift, addr, 3); + slli(shift, shift, 3); + + andi(aligned_addr, addr, ~3); + + if (size == int8) { + addi(mask, zr, 0xff); + } else { + // size == int16 case + addi(mask, zr, -1); + zero_extend(mask, mask, 16); + } + sll(mask, mask, shift); + + xori(not_mask, mask, -1); + + sll(expected, expected, shift); + andr(expected, expected, mask); + + sll(new_val, new_val, shift); + andr(new_val, new_val, mask); +} + +// cmpxchg_narrow_value will kill t0, t1, expected, new_val and tmps. +// It's designed to implement compare and swap byte/boolean/char/short by lr.w/sc.w, +// which are forced to work with 4-byte aligned address. +void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, bool result_as_bool, + Register tmp1, Register tmp2, Register tmp3) { + Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0; + assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp); + cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3); + + Label retry, fail, done; + + bind(retry); + lr_w(old, aligned_addr, acquire); + andr(tmp, old, mask); + bne(tmp, expected, fail); + + andr(tmp, old, not_mask); + orr(tmp, tmp, new_val); + sc_w(tmp, tmp, aligned_addr, release); + bnez(tmp, retry); + + if (result_as_bool) { + addi(result, zr, 1); + j(done); + + bind(fail); + mv(result, zr); + + bind(done); + } else { + andr(tmp, old, mask); + + bind(fail); + srl(result, tmp, shift); + + if (size == int8) { + sign_extend(result, result, 8); + } else { + // size == int16 case + sign_extend(result, result, 16); + } + } +} + +// weak_cmpxchg_narrow_value is a weak version of cmpxchg_narrow_value, to implement +// the weak CAS stuff. The major difference is that it just failed when store conditional +// failed. +void MacroAssembler::weak_cmpxchg_narrow_value(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, + Register tmp1, Register tmp2, Register tmp3) { + Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0; + assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp); + cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3); + + Label succ, fail, done; + + lr_w(old, aligned_addr, acquire); + andr(tmp, old, mask); + bne(tmp, expected, fail); + + andr(tmp, old, not_mask); + orr(tmp, tmp, new_val); + sc_w(tmp, tmp, aligned_addr, release); + beqz(tmp, succ); + + bind(fail); + addi(result, zr, 1); + j(done); + + bind(succ); + mv(result, zr); + + bind(done); +} + +void MacroAssembler::cmpxchg(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, bool result_as_bool) { + assert(size != int8 && size != int16, "unsupported operand size"); + + Label retry_load, done, ne_done; + bind(retry_load); + load_reserved(addr, size, acquire); + bne(t0, expected, ne_done); + store_conditional(addr, new_val, size, release); + bnez(t0, retry_load); + + // equal, succeed + if (result_as_bool) { + li(result, 1); + } else { + mv(result, expected); + } + j(done); + + // not equal, failed + bind(ne_done); + if (result_as_bool) { + mv(result, zr); + } else { + mv(result, t0); + } + + bind(done); +} + +void MacroAssembler::cmpxchg_weak(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result) { + Label fail, done, sc_done; + load_reserved(addr, size, acquire); + bne(t0, expected, fail); + store_conditional(addr, new_val, size, release); + beqz(t0, sc_done); + + // fail + bind(fail); + li(result, 1); + j(done); + + // sc_done + bind(sc_done); + mv(result, 0); + bind(done); +} + +#define ATOMIC_OP(NAME, AOP, ACQUIRE, RELEASE) \ +void MacroAssembler::atomic_##NAME(Register prev, RegisterOrConstant incr, Register addr) { \ + prev = prev->is_valid() ? prev : zr; \ + if (incr.is_register()) { \ + AOP(prev, addr, incr.as_register(), (Assembler::Aqrl)(ACQUIRE | RELEASE)); \ + } else { \ + mv(t0, incr.as_constant()); \ + AOP(prev, addr, t0, (Assembler::Aqrl)(ACQUIRE | RELEASE)); \ + } \ + return; \ +} + +ATOMIC_OP(add, amoadd_d, Assembler::relaxed, Assembler::relaxed) +ATOMIC_OP(addw, amoadd_w, Assembler::relaxed, Assembler::relaxed) +ATOMIC_OP(addal, amoadd_d, Assembler::aq, Assembler::rl) +ATOMIC_OP(addalw, amoadd_w, Assembler::aq, Assembler::rl) + +#undef ATOMIC_OP + +#define ATOMIC_XCHG(OP, AOP, ACQUIRE, RELEASE) \ +void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { \ + prev = prev->is_valid() ? prev : zr; \ + AOP(prev, addr, newv, (Assembler::Aqrl)(ACQUIRE | RELEASE)); \ + return; \ +} + +ATOMIC_XCHG(xchg, amoswap_d, Assembler::relaxed, Assembler::relaxed) +ATOMIC_XCHG(xchgw, amoswap_w, Assembler::relaxed, Assembler::relaxed) +ATOMIC_XCHG(xchgal, amoswap_d, Assembler::aq, Assembler::rl) +ATOMIC_XCHG(xchgalw, amoswap_w, Assembler::aq, Assembler::rl) + +#undef ATOMIC_XCHG + +#define ATOMIC_XCHGU(OP1, OP2) \ +void MacroAssembler::atomic_##OP1(Register prev, Register newv, Register addr) { \ + atomic_##OP2(prev, newv, addr); \ + zero_extend(prev, prev, 32); \ + return; \ +} + +ATOMIC_XCHGU(xchgwu, xchgw) +ATOMIC_XCHGU(xchgalwu, xchgalw) + +#undef ATOMIC_XCHGU + +void MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) { + assert(ReservedCodeCacheSize < 4*G, "branch out of range"); + assert(CodeCache::find_blob(entry.target()) != NULL, + "destination of far call not found in code cache"); + int32_t offset = 0; + if (far_branches()) { + // We can use auipc + jalr here because we know that the total size of + // the code cache cannot exceed 2Gb. + la_patchable(tmp, entry, offset); + if (cbuf != NULL) { cbuf->set_insts_mark(); } + jalr(x0, tmp, offset); + } else { + if (cbuf != NULL) { cbuf->set_insts_mark(); } + j(entry); + } +} + +void MacroAssembler::far_call(Address entry, CodeBuffer *cbuf, Register tmp) { + assert(ReservedCodeCacheSize < 4*G, "branch out of range"); + assert(CodeCache::find_blob(entry.target()) != NULL, + "destination of far call not found in code cache"); + int32_t offset = 0; + if (far_branches()) { + // We can use auipc + jalr here because we know that the total size of + // the code cache cannot exceed 2Gb. + la_patchable(tmp, entry, offset); + if (cbuf != NULL) { cbuf->set_insts_mark(); } + jalr(x1, tmp, offset); // link + } else { + if (cbuf != NULL) { cbuf->set_insts_mark(); } + jal(entry); // link + } +} + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register tmp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + Register super_check_offset) { + assert_different_registers(sub_klass, super_klass, tmp_reg); + bool must_load_sco = (super_check_offset == noreg); + if (must_load_sco) { + assert(tmp_reg != noreg, "supply either a temp or a register offset"); + } else { + assert_different_registers(sub_klass, super_klass, super_check_offset); + } + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in batch"); + + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + Address super_check_offset_addr(super_klass, sco_offset); + + // Hacked jmp, which may only be used just before L_fallthrough. +#define final_jmp(label) \ + if (&(label) == &L_fallthrough) { /*do nothing*/ } \ + else j(label) /*omit semi*/ + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front fo the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + beq(sub_klass, super_klass, *L_success); + + // Check the supertype display: + if (must_load_sco) { + lwu(tmp_reg, super_check_offset_addr); + super_check_offset = tmp_reg; + } + add(t0, sub_klass, super_check_offset); + Address super_check_addr(t0); + ld(t0, super_check_addr); // load displayed supertype + + // Ths check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_Cache and the primary super dispaly elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + beq(super_klass, t0, *L_success); + mv(t1, sc_offset); + if (L_failure == &L_fallthrough) { + beq(super_check_offset, t1, *L_slow_path); + } else { + bne(super_check_offset, t1, *L_failure, /* is_far */ true); + final_jmp(*L_slow_path); + } + + bind(L_fallthrough); + +#undef final_jmp +} + +// Scans count pointer sized words at [addr] for occurence of value, +// generic +void MacroAssembler::repne_scan(Register addr, Register value, Register count, + Register tmp) { + Label Lloop, Lexit; + beqz(count, Lexit); + bind(Lloop); + ld(tmp, addr); + beq(value, tmp, Lexit); + add(addr, addr, wordSize); + sub(count, count, 1); + bnez(count, Lloop); + bind(Lexit); +} + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure) { + assert_different_registers(sub_klass, super_klass, tmp1_reg); + if (tmp2_reg != noreg) { + assert_different_registers(sub_klass, super_klass, tmp1_reg, tmp2_reg, t0); + } +#define IS_A_TEMP(reg) ((reg) == tmp1_reg || (reg) == tmp2_reg) + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + + assert(label_nulls <= 1, "at most one NULL in the batch"); + + // A couple of usefule fields in sub_klass: + int ss_offset = in_bytes(Klass::secondary_supers_offset()); + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + Address secondary_supers_addr(sub_klass, ss_offset); + Address super_cache_addr( sub_klass, sc_offset); + + BLOCK_COMMENT("check_klass_subtype_slow_path"); + + // Do a linear scan of the secondary super-klass chain. + // This code is rarely used, so simplicity is a virtue here. + // The repne_scan instruction uses fixed registers, which we must spill. + // Don't worry too much about pre-existing connecitons with the input regs. + + assert(sub_klass != x10, "killed reg"); // killed by mv(x10, super) + assert(sub_klass != x12, "killed reg"); // killed by la(x12, &pst_counter) + + RegSet pushed_registers; + if (!IS_A_TEMP(x12)) { + pushed_registers += x12; + } + if (!IS_A_TEMP(x15)) { + pushed_registers += x15; + } + + if (super_klass != x10 || UseCompressedOops) { + if (!IS_A_TEMP(x10)) { + pushed_registers += x10; + } + } + + push_reg(pushed_registers, sp); + + // Get super_klass value into x10 (even if it was in x15 or x12) + mv(x10, super_klass); + +#ifndef PRODUCT + mv(t1, (address)&SharedRuntime::_partial_subtype_ctr); + Address pst_counter_addr(t1); + ld(t0, pst_counter_addr); + add(t0, t0, 1); + sd(t0, pst_counter_addr); +#endif // PRODUCT + + // We will consult the secondary-super array. + ld(x15, secondary_supers_addr); + // Load the array length. + lwu(x12, Address(x15, Array::length_offset_in_bytes())); + // Skip to start of data. + add(x15, x15, Array::base_offset_in_bytes()); + + // Set t0 to an obvious invalid value, falling through by default + li(t0, -1); + // Scan X12 words at [X15] for an occurrence of X10. + repne_scan(x15, x10, x12, t0); + + // pop will restore x10, so we should use a temp register to keep its value + mv(t1, x10); + + // Unspill the temp registers: + pop_reg(pushed_registers, sp); + + bne(t1, t0, *L_failure); + + // Success. Cache the super we found an proceed in triumph. + sd(super_klass, super_cache_addr); + + if (L_success != &L_fallthrough) { + j(*L_success); + } + +#undef IS_A_TEMP + + bind(L_fallthrough); +} + +// Defines obj, preserves var_size_in_bytes, okay for tmp2 == var_size_in_bytes. +void MacroAssembler::tlab_allocate(Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp1, + Register tmp2, + Label& slow_case, + bool is_far) { + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, tmp1, tmp2, slow_case, is_far); +} + +// Defines obj, preserves var_size_in_bytes +void MacroAssembler::eden_allocate(Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp, + Label& slow_case, + bool is_far) { + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->eden_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, tmp, slow_case, is_far); +} + + +// get_thread() can be called anywhere inside generated code so we +// need to save whatever non-callee save context might get clobbered +// by the call to Thread::current() or, indeed, the call setup code. +void MacroAssembler::get_thread(Register thread) { + // save all call-clobbered regs except thread + RegSet saved_regs = RegSet::range(x5, x7) + RegSet::range(x10, x17) + + RegSet::range(x28, x31) + ra - thread; + push_reg(saved_regs, sp); + + int32_t offset = 0; + movptr_with_offset(ra, CAST_FROM_FN_PTR(address, Thread::current), offset); + jalr(ra, ra, offset); + if (thread != x10) { + mv(thread, x10); + } + + // restore pushed registers + pop_reg(saved_regs, sp); +} + +void MacroAssembler::load_byte_map_base(Register reg) { + CardTable::CardValue* byte_map_base = + ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base(); + li(reg, (uint64_t)byte_map_base); +} + +void MacroAssembler::la_patchable(Register reg1, const Address &dest, int32_t &offset) { + relocInfo::relocType rtype = dest.rspec().reloc()->type(); + unsigned long low_address = (uintptr_t)CodeCache::low_bound(); + unsigned long high_address = (uintptr_t)CodeCache::high_bound(); + unsigned long dest_address = (uintptr_t)dest.target(); + long offset_low = dest_address - low_address; + long offset_high = dest_address - high_address; + + assert(is_valid_riscv64_address(dest.target()), "bad address"); + assert(dest.getMode() == Address::literal, "la_patchable must be applied to a literal address"); + + InstructionMark im(this); + code_section()->relocate(inst_mark(), dest.rspec()); + // RISC-V doesn't compute a page-aligned address, in order to partially + // compensate for the use of *signed* offsets in its base+disp12 + // addressing mode (RISC-V's PC-relative reach remains asymmetric + // [-(2G + 2K), 2G - 2k). + if (offset_high >= -((1L << 31) + (1L << 11)) && offset_low < (1L << 31) - (1L << 11)) { + int64_t distance = dest.target() - pc(); + auipc(reg1, (int32_t)distance + 0x800); + offset = ((int32_t)distance << 20) >> 20; + } else { + movptr_with_offset(reg1, dest.target(), offset); + } +} + +void MacroAssembler::build_frame(int framesize) { + assert(framesize >= 2, "framesize must include space for FP/RA"); + assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment"); + sub(sp, sp, framesize); + sd(fp, Address(sp, framesize - 2 * wordSize)); + sd(ra, Address(sp, framesize - wordSize)); + if (PreserveFramePointer) { add(fp, sp, framesize); } + verify_cross_modify_fence_not_required(); +} + +void MacroAssembler::remove_frame(int framesize) { + assert(framesize >= 2, "framesize must include space for FP/RA"); + assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment"); + ld(fp, Address(sp, framesize - 2 * wordSize)); + ld(ra, Address(sp, framesize - wordSize)); + add(sp, sp, framesize); +} + +void MacroAssembler::reserved_stack_check() { + // testing if reserved zone needs to be enabled + Label no_reserved_zone_enabling; + + ld(t0, Address(xthread, JavaThread::reserved_stack_activation_offset())); + bltu(sp, t0, no_reserved_zone_enabling); + + enter(); // RA and FP are live. + mv(c_rarg0, xthread); + int32_t offset = 0; + la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone)), offset); + jalr(x1, t0, offset); + leave(); + + // We have already removed our own frame. + // throw_delayed_StackOverflowError will think that it's been + // called by our caller. + offset = 0; + la_patchable(t0, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()), offset); + jalr(x0, t0, offset); + should_not_reach_here(); + + bind(no_reserved_zone_enabling); +} + +// Move the address of the polling page into dest. +void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype) { + ld(dest, Address(xthread, JavaThread::polling_page_offset())); +} + +// Read the polling page. The address of the polling page must +// already be in r. +address MacroAssembler::read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype) { + address mark; + { + InstructionMark im(this); + code_section()->relocate(inst_mark(), rtype); + lwu(zr, Address(r, offset)); + mark = inst_mark(); + } + verify_cross_modify_fence_not_required(); + return mark; +} + +void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { +#ifdef ASSERT + { + ThreadInVMfromUnknown tiv; + assert (UseCompressedOops, "should only be used for compressed oops"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); + } +#endif + int oop_index = oop_recorder()->find_index(obj); + InstructionMark im(this); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + code_section()->relocate(inst_mark(), rspec); + li32(dst, 0xDEADBEEF); + zero_extend(dst, dst, 32); +} + +void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { + assert (UseCompressedClassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int index = oop_recorder()->find_index(k); + assert(!Universe::heap()->is_in(k), "should not be an oop"); + + InstructionMark im(this); + RelocationHolder rspec = metadata_Relocation::spec(index); + code_section()->relocate(inst_mark(), rspec); + narrowKlass nk = CompressedKlassPointers::encode(k); + li32(dst, nk); + zero_extend(dst, dst, 32); +} + +// Maybe emit a call via a trampoline. If the code cache is small +// trampolines won't be emitted. +address MacroAssembler::trampoline_call(Address entry, CodeBuffer* cbuf) { + assert(JavaThread::current()->is_Compiler_thread(), "just checking"); + assert(entry.rspec().type() == relocInfo::runtime_call_type || + entry.rspec().type() == relocInfo::opt_virtual_call_type || + entry.rspec().type() == relocInfo::static_call_type || + entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type"); + + // We need a trampoline if branches are far. + if (far_branches()) { + bool in_scratch_emit_size = false; +#ifdef COMPILER2 + // We don't want to emit a trampoline if C2 is generating dummy + // code during its branch shortening phase. + CompileTask* task = ciEnv::current()->task(); + in_scratch_emit_size = + (task != NULL && is_c2_compile(task->comp_level()) && + Compile::current()->output()->in_scratch_emit_size()); +#endif + if (!in_scratch_emit_size) { + address stub = emit_trampoline_stub(offset(), entry.target()); + if (stub == NULL) { + postcond(pc() == badAddress); + return NULL; // CodeCache is full + } + } + } + + if (cbuf != NULL) { cbuf->set_insts_mark(); } + relocate(entry.rspec()); + if (!far_branches()) { + jal(entry.target()); + } else { + jal(pc()); + } + // just need to return a non-null address + postcond(pc() != badAddress); + return pc(); +} + +address MacroAssembler::ic_call(address entry, jint method_index) { + RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); + movptr(t1, (address)Universe::non_oop_word()); + assert_cond(entry != NULL); + return trampoline_call(Address(entry, rh)); +} + +// Emit a trampoline stub for a call to a target which is too far away. +// +// code sequences: +// +// call-site: +// branch-and-link to or +// +// Related trampoline stub for this call site in the stub section: +// load the call target from the constant pool +// branch (RA still points to the call site above) + +address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, + address dest) { + address stub = start_a_stub(NativeInstruction::instruction_size + + NativeCallTrampolineStub::instruction_size); + if (stub == NULL) { + return NULL; // CodeBuffer::expand failed + } + + // Create a trampoline stub relocation which relates this trampoline stub + // with the call instruction at insts_call_instruction_offset in the + // instructions code-section. + + // make sure 4 byte aligned here, so that the destination address would be + // 8 byte aligned after 3 intructions + // when we reach here we may get a 2-byte alignment so need to align it + align(wordSize, NativeCallTrampolineStub::data_offset); + + relocate(trampoline_stub_Relocation::spec(code()->insts()->start() + + insts_call_instruction_offset)); + const int stub_start_offset = offset(); + + // Now, create the trampoline stub's code: + // - load the call + // - call + Label target; + ld(t0, target); // auipc + ld + jr(t0); // jalr + bind(target); + assert(offset() - stub_start_offset == NativeCallTrampolineStub::data_offset, + "should be"); + assert(offset() % wordSize == 0, "bad alignment"); + emit_int64((intptr_t)dest); + + const address stub_start_addr = addr_at(stub_start_offset); + + assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline"); + + end_a_stub(); + return stub_start_addr; +} + +Address MacroAssembler::add_memory_helper(const Address dst) { + switch (dst.getMode()) { + case Address::base_plus_offset: + // This is the expected mode, although we allow all the other + // forms below. + return form_address(t1, dst.base(), dst.offset()); + default: + la(t1, dst); + return Address(t1); + } +} + +void MacroAssembler::add_memory_int64(const Address dst, int64_t imm) { + Address adr = add_memory_helper(dst); + assert_different_registers(adr.base(), t0); + ld(t0, adr); + addi(t0, t0, imm); + sd(t0, adr); +} + +void MacroAssembler::add_memory_int32(const Address dst, int32_t imm) { + Address adr = add_memory_helper(dst); + assert_different_registers(adr.base(), t0); + lwu(t0, adr); + addiw(t0, t0, imm); + sw(t0, adr); +} + +void MacroAssembler::cmpptr(Register src1, Address src2, Label& equal) { + assert_different_registers(src1, t0); + int32_t offset; + la_patchable(t0, src2, offset); + ld(t0, Address(t0, offset)); + beq(src1, t0, equal); +} + +void MacroAssembler::load_method_holder_cld(Register result, Register method) { + load_method_holder(result, method); + ld(result, Address(result, InstanceKlass::class_loader_data_offset())); +} + +void MacroAssembler::load_method_holder(Register holder, Register method) { + ld(holder, Address(method, Method::const_offset())); // ConstMethod* + ld(holder, Address(holder, ConstMethod::constants_offset())); // ConstantPool* + ld(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass* +} + +// string indexof +// compute index by trailing zeros +void MacroAssembler::compute_index(Register haystack, Register trailing_zeros, + Register match_mask, Register result, + Register ch2, Register tmp, + bool haystack_isL) +{ + int haystack_chr_shift = haystack_isL ? 0 : 1; + srl(match_mask, match_mask, trailing_zeros); + srli(match_mask, match_mask, 1); + srli(tmp, trailing_zeros, LogBitsPerByte); + if (!haystack_isL) andi(tmp, tmp, 0xE); + add(haystack, haystack, tmp); + ld(ch2, Address(haystack)); + if (!haystack_isL) srli(tmp, tmp, haystack_chr_shift); + add(result, result, tmp); +} + +// string indexof +// Find pattern element in src, compute match mask, +// only the first occurrence of 0x80/0x8000 at low bits is the valid match index +// match mask patterns and corresponding indices would be like: +// - 0x8080808080808080 (Latin1) +// - 7 6 5 4 3 2 1 0 (match index) +// - 0x8000800080008000 (UTF16) +// - 3 2 1 0 (match index) +void MacroAssembler::compute_match_mask(Register src, Register pattern, Register match_mask, + Register mask1, Register mask2) +{ + xorr(src, pattern, src); + sub(match_mask, src, mask1); + orr(src, src, mask2); + notr(src, src); + andr(match_mask, match_mask, src); +} + +#ifdef COMPILER2 +// Code for BigInteger::mulAdd instrinsic +// out = x10 +// in = x11 +// offset = x12 (already out.length-offset) +// len = x13 +// k = x14 +// tmp = x28 +// +// pseudo code from java implementation: +// long kLong = k & LONG_MASK; +// carry = 0; +// offset = out.length-offset - 1; +// for (int j = len - 1; j >= 0; j--) { +// product = (in[j] & LONG_MASK) * kLong + (out[offset] & LONG_MASK) + carry; +// out[offset--] = (int)product; +// carry = product >>> 32; +// } +// return (int)carry; +void MacroAssembler::mul_add(Register out, Register in, Register offset, + Register len, Register k, Register tmp) { + Label L_tail_loop, L_unroll, L_end; + mv(tmp, out); + mv(out, zr); + blez(len, L_end); + zero_extend(k, k, 32); + slliw(t0, offset, LogBytesPerInt); + add(offset, tmp, t0); + slliw(t0, len, LogBytesPerInt); + add(in, in, t0); + + const int unroll = 8; + li(tmp, unroll); + blt(len, tmp, L_tail_loop); + bind(L_unroll); + for (int i = 0; i < unroll; i++) { + sub(in, in, BytesPerInt); + lwu(t0, Address(in, 0)); + mul(t1, t0, k); + add(t0, t1, out); + sub(offset, offset, BytesPerInt); + lwu(t1, Address(offset, 0)); + add(t0, t0, t1); + sw(t0, Address(offset, 0)); + srli(out, t0, 32); + } + subw(len, len, tmp); + bge(len, tmp, L_unroll); + + bind(L_tail_loop); + blez(len, L_end); + sub(in, in, BytesPerInt); + lwu(t0, Address(in, 0)); + mul(t1, t0, k); + add(t0, t1, out); + sub(offset, offset, BytesPerInt); + lwu(t1, Address(offset, 0)); + add(t0, t0, t1); + sw(t0, Address(offset, 0)); + srli(out, t0, 32); + subw(len, len, 1); + j(L_tail_loop); + + bind(L_end); +} + +// add two unsigned input and output carry +void MacroAssembler::cad(Register dst, Register src1, Register src2, Register carry) +{ + assert_different_registers(dst, carry); + assert_different_registers(dst, src2); + add(dst, src1, src2); + sltu(carry, dst, src2); +} + +// add two input with carry +void MacroAssembler::adc(Register dst, Register src1, Register src2, Register carry) +{ + assert_different_registers(dst, carry); + add(dst, src1, src2); + add(dst, dst, carry); +} + +// add two unsigned input with carry and output carry +void MacroAssembler::cadc(Register dst, Register src1, Register src2, Register carry) +{ + assert_different_registers(dst, src2); + adc(dst, src1, src2, carry); + sltu(carry, dst, src2); +} + +void MacroAssembler::add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo, + Register src1, Register src2, Register carry) +{ + cad(dest_lo, dest_lo, src1, carry); + add(dest_hi, dest_hi, carry); + cad(dest_lo, dest_lo, src2, carry); + add(final_dest_hi, dest_hi, carry); +} + +/** + * Multiply 32 bit by 32 bit first loop. + */ +void MacroAssembler::multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, + Register y, Register y_idx, Register z, + Register carry, Register product, + Register idx, Register kdx) +{ + // jlong carry, x[], y[], z[]; + // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) { + // long product = y[idx] * x[xstart] + carry; + // z[kdx] = (int)product; + // carry = product >>> 32; + // } + // z[xstart] = (int)carry; + + Label L_first_loop, L_first_loop_exit; + blez(idx, L_first_loop_exit); + + shadd(t0, xstart, x, t0, LogBytesPerInt); + lwu(x_xstart, Address(t0, 0)); + + bind(L_first_loop); + subw(idx, idx, 1); + shadd(t0, idx, y, t0, LogBytesPerInt); + lwu(y_idx, Address(t0, 0)); + mul(product, x_xstart, y_idx); + add(product, product, carry); + srli(carry, product, 32); + subw(kdx, kdx, 1); + shadd(t0, kdx, z, t0, LogBytesPerInt); + sw(product, Address(t0, 0)); + bgtz(idx, L_first_loop); + + bind(L_first_loop_exit); +} + +/** + * Multiply 64 bit by 64 bit first loop. + */ +void MacroAssembler::multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, + Register y, Register y_idx, Register z, + Register carry, Register product, + Register idx, Register kdx) +{ + // + // jlong carry, x[], y[], z[]; + // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) { + // huge_128 product = y[idx] * x[xstart] + carry; + // z[kdx] = (jlong)product; + // carry = (jlong)(product >>> 64); + // } + // z[xstart] = carry; + // + + Label L_first_loop, L_first_loop_exit; + Label L_one_x, L_one_y, L_multiply; + + subw(xstart, xstart, 1); + bltz(xstart, L_one_x); + + shadd(t0, xstart, x, t0, LogBytesPerInt); + ld(x_xstart, Address(t0, 0)); + ror_imm(x_xstart, x_xstart, 32); // convert big-endian to little-endian + + bind(L_first_loop); + subw(idx, idx, 1); + bltz(idx, L_first_loop_exit); + subw(idx, idx, 1); + bltz(idx, L_one_y); + + shadd(t0, idx, y, t0, LogBytesPerInt); + ld(y_idx, Address(t0, 0)); + ror_imm(y_idx, y_idx, 32); // convert big-endian to little-endian + bind(L_multiply); + + mulhu(t0, x_xstart, y_idx); + mul(product, x_xstart, y_idx); + cad(product, product, carry, t1); + adc(carry, t0, zr, t1); + + subw(kdx, kdx, 2); + ror_imm(product, product, 32); // back to big-endian + shadd(t0, kdx, z, t0, LogBytesPerInt); + sd(product, Address(t0, 0)); + + j(L_first_loop); + + bind(L_one_y); + lwu(y_idx, Address(y, 0)); + j(L_multiply); + + bind(L_one_x); + lwu(x_xstart, Address(x, 0)); + j(L_first_loop); + + bind(L_first_loop_exit); +} + +/** + * Multiply 128 bit by 128 bit. Unrolled inner loop. + * + */ +void MacroAssembler::multiply_128_x_128_loop(Register y, Register z, + Register carry, Register carry2, + Register idx, Register jdx, + Register yz_idx1, Register yz_idx2, + Register tmp, Register tmp3, Register tmp4, + Register tmp6, Register product_hi) +{ + // jlong carry, x[], y[], z[]; + // int kdx = xstart+1; + // for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop + // huge_128 tmp3 = (y[idx+1] * product_hi) + z[kdx+idx+1] + carry; + // jlong carry2 = (jlong)(tmp3 >>> 64); + // huge_128 tmp4 = (y[idx] * product_hi) + z[kdx+idx] + carry2; + // carry = (jlong)(tmp4 >>> 64); + // z[kdx+idx+1] = (jlong)tmp3; + // z[kdx+idx] = (jlong)tmp4; + // } + // idx += 2; + // if (idx > 0) { + // yz_idx1 = (y[idx] * product_hi) + z[kdx+idx] + carry; + // z[kdx+idx] = (jlong)yz_idx1; + // carry = (jlong)(yz_idx1 >>> 64); + // } + // + + Label L_third_loop, L_third_loop_exit, L_post_third_loop_done; + + srliw(jdx, idx, 2); + + bind(L_third_loop); + + subw(jdx, jdx, 1); + bltz(jdx, L_third_loop_exit); + subw(idx, idx, 4); + + shadd(t0, idx, y, t0, LogBytesPerInt); + ld(yz_idx2, Address(t0, 0)); + ld(yz_idx1, Address(t0, wordSize)); + + shadd(tmp6, idx, z, t0, LogBytesPerInt); + + ror_imm(yz_idx1, yz_idx1, 32); // convert big-endian to little-endian + ror_imm(yz_idx2, yz_idx2, 32); + + ld(t1, Address(tmp6, 0)); + ld(t0, Address(tmp6, wordSize)); + + mul(tmp3, product_hi, yz_idx1); // yz_idx1 * product_hi -> tmp4:tmp3 + mulhu(tmp4, product_hi, yz_idx1); + + ror_imm(t0, t0, 32, tmp); // convert big-endian to little-endian + ror_imm(t1, t1, 32, tmp); + + mul(tmp, product_hi, yz_idx2); // yz_idx2 * product_hi -> carry2:tmp + mulhu(carry2, product_hi, yz_idx2); + + cad(tmp3, tmp3, carry, carry); + adc(tmp4, tmp4, zr, carry); + cad(tmp3, tmp3, t0, t0); + cadc(tmp4, tmp4, tmp, t0); + adc(carry, carry2, zr, t0); + cad(tmp4, tmp4, t1, carry2); + adc(carry, carry, zr, carry2); + + ror_imm(tmp3, tmp3, 32); // convert little-endian to big-endian + ror_imm(tmp4, tmp4, 32); + sd(tmp4, Address(tmp6, 0)); + sd(tmp3, Address(tmp6, wordSize)); + + j(L_third_loop); + + bind(L_third_loop_exit); + + andi(idx, idx, 0x3); + beqz(idx, L_post_third_loop_done); + + Label L_check_1; + subw(idx, idx, 2); + bltz(idx, L_check_1); + + shadd(t0, idx, y, t0, LogBytesPerInt); + ld(yz_idx1, Address(t0, 0)); + ror_imm(yz_idx1, yz_idx1, 32); + + mul(tmp3, product_hi, yz_idx1); // yz_idx1 * product_hi -> tmp4:tmp3 + mulhu(tmp4, product_hi, yz_idx1); + + shadd(t0, idx, z, t0, LogBytesPerInt); + ld(yz_idx2, Address(t0, 0)); + ror_imm(yz_idx2, yz_idx2, 32, tmp); + + add2_with_carry(carry, tmp4, tmp3, carry, yz_idx2, tmp); + + ror_imm(tmp3, tmp3, 32, tmp); + sd(tmp3, Address(t0, 0)); + + bind(L_check_1); + + andi(idx, idx, 0x1); + subw(idx, idx, 1); + bltz(idx, L_post_third_loop_done); + shadd(t0, idx, y, t0, LogBytesPerInt); + lwu(tmp4, Address(t0, 0)); + mul(tmp3, tmp4, product_hi); // tmp4 * product_hi -> carry2:tmp3 + mulhu(carry2, tmp4, product_hi); + + shadd(t0, idx, z, t0, LogBytesPerInt); + lwu(tmp4, Address(t0, 0)); + + add2_with_carry(carry2, carry2, tmp3, tmp4, carry, t0); + + shadd(t0, idx, z, t0, LogBytesPerInt); + sw(tmp3, Address(t0, 0)); + + slli(t0, carry2, 32); + srli(carry, tmp3, 32); + orr(carry, carry, t0); + + bind(L_post_third_loop_done); +} + +/** + * Code for BigInteger::multiplyToLen() intrinsic. + * + * x10: x + * x11: xlen + * x12: y + * x13: ylen + * x14: z + * x15: zlen + * x16: tmp1 + * x17: tmp2 + * x7: tmp3 + * x28: tmp4 + * x29: tmp5 + * x30: tmp6 + * x31: tmp7 + */ +void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Register ylen, + Register z, Register zlen, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, + Register tmp5, Register tmp6, Register product_hi) +{ + assert_different_registers(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); + + const Register idx = tmp1; + const Register kdx = tmp2; + const Register xstart = tmp3; + + const Register y_idx = tmp4; + const Register carry = tmp5; + const Register product = xlen; + const Register x_xstart = zlen; // reuse register + + mv(idx, ylen); // idx = ylen; + mv(kdx, zlen); // kdx = xlen+ylen; + mv(carry, zr); // carry = 0; + + Label L_multiply_64_x_64_loop, L_done; + + subw(xstart, xlen, 1); + bltz(xstart, L_done); + + const Register jdx = tmp1; + + if (AvoidUnalignedAccesses) { + // Check if x and y are both 8-byte aligned. + orr(t0, xlen, ylen); + andi(t0, t0, 0x1); + beqz(t0, L_multiply_64_x_64_loop); + + multiply_32_x_32_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); + shadd(t0, xstart, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + + Label L_second_loop_unaligned; + bind(L_second_loop_unaligned); + mv(carry, zr); + mv(jdx, ylen); + subw(xstart, xstart, 1); + bltz(xstart, L_done); + sub(sp, sp, 2 * wordSize); + sd(z, Address(sp, 0)); + sd(zr, Address(sp, wordSize)); + shadd(t0, xstart, z, t0, LogBytesPerInt); + addi(z, t0, 4); + shadd(t0, xstart, x, t0, LogBytesPerInt); + lwu(product, Address(t0, 0)); + Label L_third_loop, L_third_loop_exit; + + blez(jdx, L_third_loop_exit); + + bind(L_third_loop); + subw(jdx, jdx, 1); + shadd(t0, jdx, y, t0, LogBytesPerInt); + lwu(t0, Address(t0, 0)); + mul(t1, t0, product); + add(t0, t1, carry); + shadd(tmp6, jdx, z, t1, LogBytesPerInt); + lwu(t1, Address(tmp6, 0)); + add(t0, t0, t1); + sw(t0, Address(tmp6, 0)); + srli(carry, t0, 32); + bgtz(jdx, L_third_loop); + + bind(L_third_loop_exit); + ld(z, Address(sp, 0)); + addi(sp, sp, 2 * wordSize); + shadd(t0, xstart, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + + j(L_second_loop_unaligned); + } + + bind(L_multiply_64_x_64_loop); + multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); + + Label L_second_loop_aligned; + beqz(kdx, L_second_loop_aligned); + + Label L_carry; + subw(kdx, kdx, 1); + beqz(kdx, L_carry); + + shadd(t0, kdx, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + srli(carry, carry, 32); + subw(kdx, kdx, 1); + + bind(L_carry); + shadd(t0, kdx, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + + // Second and third (nested) loops. + // + // for (int i = xstart-1; i >= 0; i--) { // Second loop + // carry = 0; + // for (int jdx=ystart, k=ystart+1+i; jdx >= 0; jdx--, k--) { // Third loop + // long product = (y[jdx] & LONG_MASK) * (x[i] & LONG_MASK) + + // (z[k] & LONG_MASK) + carry; + // z[k] = (int)product; + // carry = product >>> 32; + // } + // z[i] = (int)carry; + // } + // + // i = xlen, j = tmp1, k = tmp2, carry = tmp5, x[i] = product_hi + + bind(L_second_loop_aligned); + mv(carry, zr); // carry = 0; + mv(jdx, ylen); // j = ystart+1 + + subw(xstart, xstart, 1); // i = xstart-1; + bltz(xstart, L_done); + + sub(sp, sp, 4 * wordSize); + sd(z, Address(sp, 0)); + + Label L_last_x; + shadd(t0, xstart, z, t0, LogBytesPerInt); + addi(z, t0, 4); + subw(xstart, xstart, 1); // i = xstart-1; + bltz(xstart, L_last_x); + + shadd(t0, xstart, x, t0, LogBytesPerInt); + ld(product_hi, Address(t0, 0)); + ror_imm(product_hi, product_hi, 32); // convert big-endian to little-endian + + Label L_third_loop_prologue; + bind(L_third_loop_prologue); + + sd(ylen, Address(sp, wordSize)); + sd(x, Address(sp, 2 * wordSize)); + sd(xstart, Address(sp, 3 * wordSize)); + multiply_128_x_128_loop(y, z, carry, x, jdx, ylen, product, + tmp2, x_xstart, tmp3, tmp4, tmp6, product_hi); + ld(z, Address(sp, 0)); + ld(ylen, Address(sp, wordSize)); + ld(x, Address(sp, 2 * wordSize)); + ld(xlen, Address(sp, 3 * wordSize)); // copy old xstart -> xlen + addi(sp, sp, 4 * wordSize); + + addiw(tmp3, xlen, 1); + shadd(t0, tmp3, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + + subw(tmp3, tmp3, 1); + bltz(tmp3, L_done); + + srli(carry, carry, 32); + shadd(t0, tmp3, z, t0, LogBytesPerInt); + sw(carry, Address(t0, 0)); + j(L_second_loop_aligned); + + // Next infrequent code is moved outside loops. + bind(L_last_x); + lwu(product_hi, Address(x, 0)); + j(L_third_loop_prologue); + + bind(L_done); +} +#endif + +// Count bits of trailing zero chars from lsb to msb until first non-zero element. +// For LL case, one byte for one element, so shift 8 bits once, and for other case, +// shift 16 bits once. +void MacroAssembler::ctzc_bit(Register Rd, Register Rs, bool isLL, Register tmp1, Register tmp2) +{ + if (UseZbb) { + assert_different_registers(Rd, Rs, tmp1); + int step = isLL ? 8 : 16; + ctz(Rd, Rs); + andi(tmp1, Rd, step - 1); + sub(Rd, Rd, tmp1); + return; + } + assert_different_registers(Rd, Rs, tmp1, tmp2); + Label Loop; + int step = isLL ? 8 : 16; + li(Rd, -step); + mv(tmp2, Rs); + + bind(Loop); + addi(Rd, Rd, step); + andi(tmp1, tmp2, ((1 << step) - 1)); + srli(tmp2, tmp2, step); + beqz(tmp1, Loop); +} + +// This instruction reads adjacent 4 bytes from the lower half of source register, +// inflate into a register, for example: +// Rs: A7A6A5A4A3A2A1A0 +// Rd: 00A300A200A100A0 +void MacroAssembler::inflate_lo32(Register Rd, Register Rs, Register tmp1, Register tmp2) +{ + assert_different_registers(Rd, Rs, tmp1, tmp2); + li(tmp1, 0xFF); + mv(Rd, zr); + for (int i = 0; i <= 3; i++) + { + andr(tmp2, Rs, tmp1); + if (i) { + slli(tmp2, tmp2, i * 8); + } + orr(Rd, Rd, tmp2); + if (i != 3) { + slli(tmp1, tmp1, 8); + } + } +} + +// This instruction reads adjacent 4 bytes from the upper half of source register, +// inflate into a register, for example: +// Rs: A7A6A5A4A3A2A1A0 +// Rd: 00A700A600A500A4 +void MacroAssembler::inflate_hi32(Register Rd, Register Rs, Register tmp1, Register tmp2) +{ + assert_different_registers(Rd, Rs, tmp1, tmp2); + li(tmp1, 0xFF00000000); + mv(Rd, zr); + for (int i = 0; i <= 3; i++) + { + andr(tmp2, Rs, tmp1); + orr(Rd, Rd, tmp2); + srli(Rd, Rd, 8); + if (i != 3) { + slli(tmp1, tmp1, 8); + } + } +} + +// The size of the blocks erased by the zero_blocks stub. We must +// handle anything smaller than this ourselves in zero_words(). +const int MacroAssembler::zero_words_block_size = 8; + +// zero_words() is used by C2 ClearArray patterns. It is as small as +// possible, handling small word counts locally and delegating +// anything larger to the zero_blocks stub. It is expanded many times +// in compiled code, so it is important to keep it short. + +// ptr: Address of a buffer to be zeroed. +// cnt: Count in HeapWords. +// +// ptr, cnt, and t0 are clobbered. +address MacroAssembler::zero_words(Register ptr, Register cnt) +{ + assert(is_power_of_2(zero_words_block_size), "adjust this"); + assert(ptr == x28 && cnt == x29, "mismatch in register usage"); + assert_different_registers(cnt, t0); + + BLOCK_COMMENT("zero_words {"); + mv(t0, zero_words_block_size); + Label around, done, done16; + bltu(cnt, t0, around); + { + RuntimeAddress zero_blocks = RuntimeAddress(StubRoutines::riscv::zero_blocks()); + assert(zero_blocks.target() != NULL, "zero_blocks stub has not been generated"); + if (StubRoutines::riscv::complete()) { + address tpc = trampoline_call(zero_blocks); + if (tpc == NULL) { + DEBUG_ONLY(reset_labels(around)); + postcond(pc() == badAddress); + return NULL; + } + } else { + jal(zero_blocks); + } + } + bind(around); + for (int i = zero_words_block_size >> 1; i > 1; i >>= 1) { + Label l; + andi(t0, cnt, i); + beqz(t0, l); + for (int j = 0; j < i; j++) { + sd(zr, Address(ptr, 0)); + addi(ptr, ptr, 8); + } + bind(l); + } + { + Label l; + andi(t0, cnt, 1); + beqz(t0, l); + sd(zr, Address(ptr, 0)); + bind(l); + } + BLOCK_COMMENT("} zero_words"); + postcond(pc() != badAddress); + return pc(); +} + +#define SmallArraySize (18 * BytesPerLong) + +// base: Address of a buffer to be zeroed, 8 bytes aligned. +// cnt: Immediate count in HeapWords. +void MacroAssembler::zero_words(Register base, u_int64_t cnt) +{ + assert_different_registers(base, t0, t1); + + BLOCK_COMMENT("zero_words {"); + + if (cnt <= SmallArraySize / BytesPerLong) { + for (int i = 0; i < (int)cnt; i++) { + sd(zr, Address(base, i * wordSize)); + } + } else { + const int unroll = 8; // Number of sd(zr, adr), instructions we'll unroll + int remainder = cnt % unroll; + for (int i = 0; i < remainder; i++) { + sd(zr, Address(base, i * wordSize)); + } + + Label loop; + Register cnt_reg = t0; + Register loop_base = t1; + cnt = cnt - remainder; + li(cnt_reg, cnt); + add(loop_base, base, remainder * wordSize); + bind(loop); + sub(cnt_reg, cnt_reg, unroll); + for (int i = 0; i < unroll; i++) { + sd(zr, Address(loop_base, i * wordSize)); + } + add(loop_base, loop_base, unroll * wordSize); + bnez(cnt_reg, loop); + } + + BLOCK_COMMENT("} zero_words"); +} + +// base: Address of a buffer to be filled, 8 bytes aligned. +// cnt: Count in 8-byte unit. +// value: Value to be filled with. +// base will point to the end of the buffer after filling. +void MacroAssembler::fill_words(Register base, Register cnt, Register value) +{ +// Algorithm: +// +// t0 = cnt & 7 +// cnt -= t0 +// p += t0 +// switch (t0): +// switch start: +// do while cnt +// cnt -= 8 +// p[-8] = value +// case 7: +// p[-7] = value +// case 6: +// p[-6] = value +// // ... +// case 1: +// p[-1] = value +// case 0: +// p += 8 +// do-while end +// switch end + + assert_different_registers(base, cnt, value, t0, t1); + + Label fini, skip, entry, loop; + const int unroll = 8; // Number of sd instructions we'll unroll + + beqz(cnt, fini); + + andi(t0, cnt, unroll - 1); + sub(cnt, cnt, t0); + // align 8, so first sd n % 8 = mod, next loop sd 8 * n. + shadd(base, t0, base, t1, 3); + la(t1, entry); + slli(t0, t0, 2); // sd_inst_nums * 4; t0 is cnt % 8, so t1 = t1 - sd_inst_nums * 4, 4 is sizeof(inst) + sub(t1, t1, t0); + jr(t1); + + bind(loop); + add(base, base, unroll * 8); + for (int i = -unroll; i < 0; i++) { + sd(value, Address(base, i * 8)); + } + bind(entry); + sub(cnt, cnt, unroll); + bgez(cnt, loop); + + bind(fini); +} + +#define FCVT_SAFE(FLOATCVT, FLOATEQ) \ +void MacroAssembler:: FLOATCVT##_safe(Register dst, FloatRegister src, Register tmp) { \ + Label L_Okay; \ + fscsr(zr); \ + FLOATCVT(dst, src); \ + frcsr(tmp); \ + andi(tmp, tmp, 0x1E); \ + beqz(tmp, L_Okay); \ + FLOATEQ(tmp, src, src); \ + bnez(tmp, L_Okay); \ + mv(dst, zr); \ + bind(L_Okay); \ +} + +FCVT_SAFE(fcvt_w_s, feq_s) +FCVT_SAFE(fcvt_l_s, feq_s) +FCVT_SAFE(fcvt_w_d, feq_d) +FCVT_SAFE(fcvt_l_d, feq_d) + +#undef FCVT_SAFE + +#define FCMP(FLOATTYPE, FLOATSIG) \ +void MacroAssembler::FLOATTYPE##_compare(Register result, FloatRegister Rs1, \ + FloatRegister Rs2, int unordered_result) { \ + Label Ldone; \ + if (unordered_result < 0) { \ + /* we want -1 for unordered or less than, 0 for equal and 1 for greater than. */ \ + /* installs 1 if gt else 0 */ \ + flt_##FLOATSIG(result, Rs2, Rs1); \ + /* Rs1 > Rs2, install 1 */ \ + bgtz(result, Ldone); \ + feq_##FLOATSIG(result, Rs1, Rs2); \ + addi(result, result, -1); \ + /* Rs1 = Rs2, install 0 */ \ + /* NaN or Rs1 < Rs2, install -1 */ \ + bind(Ldone); \ + } else { \ + /* we want -1 for less than, 0 for equal and 1 for unordered or greater than. */ \ + /* installs 1 if gt or unordered else 0 */ \ + flt_##FLOATSIG(result, Rs1, Rs2); \ + /* Rs1 < Rs2, install -1 */ \ + bgtz(result, Ldone); \ + feq_##FLOATSIG(result, Rs1, Rs2); \ + addi(result, result, -1); \ + /* Rs1 = Rs2, install 0 */ \ + /* NaN or Rs1 > Rs2, install 1 */ \ + bind(Ldone); \ + neg(result, result); \ + } \ +} + +FCMP(float, s); +FCMP(double, d); + +#undef FCMP + +// Zero words; len is in bytes +// Destroys all registers except addr +// len must be a nonzero multiple of wordSize +void MacroAssembler::zero_memory(Register addr, Register len, Register tmp) { + assert_different_registers(addr, len, tmp, t0, t1); + +#ifdef ASSERT + { + Label L; + andi(t0, len, BytesPerWord - 1); + beqz(t0, L); + stop("len is not a multiple of BytesPerWord"); + bind(L); + } +#endif // ASSERT + +#ifndef PRODUCT + block_comment("zero memory"); +#endif // PRODUCT + + Label loop; + Label entry; + + // Algorithm: + // + // t0 = cnt & 7 + // cnt -= t0 + // p += t0 + // switch (t0) { + // do { + // cnt -= 8 + // p[-8] = 0 + // case 7: + // p[-7] = 0 + // case 6: + // p[-6] = 0 + // ... + // case 1: + // p[-1] = 0 + // case 0: + // p += 8 + // } while (cnt) + // } + + const int unroll = 8; // Number of sd(zr) instructions we'll unroll + + srli(len, len, LogBytesPerWord); + andi(t0, len, unroll - 1); // t0 = cnt % unroll + sub(len, len, t0); // cnt -= unroll + // tmp always points to the end of the region we're about to zero + shadd(tmp, t0, addr, t1, LogBytesPerWord); + la(t1, entry); + slli(t0, t0, 2); + sub(t1, t1, t0); + jr(t1); + bind(loop); + sub(len, len, unroll); + for (int i = -unroll; i < 0; i++) { + Assembler::sd(zr, Address(tmp, i * wordSize)); + } + bind(entry); + add(tmp, tmp, unroll * wordSize); + bnez(len, loop); +} + +// shift left by shamt and add +// Rd = (Rs1 << shamt) + Rs2 +void MacroAssembler::shadd(Register Rd, Register Rs1, Register Rs2, Register tmp, int shamt) { + if (UseZba) { + if (shamt == 1) { + sh1add(Rd, Rs1, Rs2); + return; + } else if (shamt == 2) { + sh2add(Rd, Rs1, Rs2); + return; + } else if (shamt == 3) { + sh3add(Rd, Rs1, Rs2); + return; + } + } + + if (shamt != 0) { + slli(tmp, Rs1, shamt); + add(Rd, Rs2, tmp); + } else { + add(Rd, Rs1, Rs2); + } +} + +void MacroAssembler::zero_extend(Register dst, Register src, int bits) { + if (UseZba && bits == 32) { + zext_w(dst, src); + return; + } + + if (UseZbb && bits == 16) { + zext_h(dst, src); + return; + } + + if (bits == 8) { + zext_b(dst, src); + } else { + slli(dst, src, XLEN - bits); + srli(dst, dst, XLEN - bits); + } +} + +void MacroAssembler::sign_extend(Register dst, Register src, int bits) { + if (UseZbb) { + if (bits == 8) { + sext_b(dst, src); + return; + } else if (bits == 16) { + sext_h(dst, src); + return; + } + } + + if (bits == 32) { + sext_w(dst, src); + } else { + slli(dst, src, XLEN - bits); + srai(dst, dst, XLEN - bits); + } +} + +void MacroAssembler::cmp_l2i(Register dst, Register src1, Register src2, Register tmp) +{ + if (src1 == src2) { + mv(dst, zr); + return; + } + Label done; + Register left = src1; + Register right = src2; + if (dst == src1) { + assert_different_registers(dst, src2, tmp); + mv(tmp, src1); + left = tmp; + } else if (dst == src2) { + assert_different_registers(dst, src1, tmp); + mv(tmp, src2); + right = tmp; + } + + // installs 1 if gt else 0 + slt(dst, right, left); + bnez(dst, done); + slt(dst, left, right); + // dst = -1 if lt; else if eq , dst = 0 + neg(dst, dst); + bind(done); +} + +void MacroAssembler::safepoint_ifence() { + ifence(); +#ifndef PRODUCT + if (VerifyCrossModifyFence) { + // Clear the thread state. + sb(zr, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); + } +#endif +} + +#ifndef PRODUCT +void MacroAssembler::verify_cross_modify_fence_not_required() { + if (VerifyCrossModifyFence) { + // Check if thread needs a cross modify fence. + lbu(t0, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); + Label fence_not_required; + beqz(t0, fence_not_required); + // If it does then fail. + la(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure))); + mv(c_rarg0, xthread); + jalr(t0); + bind(fence_not_required); + } +} +#endif diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..23e09475be1be7430c136ee8bf4cbab050dda213 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -0,0 +1,858 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_MACROASSEMBLER_RISCV_HPP +#define CPU_RISCV_MACROASSEMBLER_RISCV_HPP + +#include "asm/assembler.hpp" +#include "metaprogramming/enableIf.hpp" +#include "oops/compressedOops.hpp" +#include "utilities/powerOfTwo.hpp" + +// MacroAssembler extends Assembler by frequently used macros. +// +// Instructions for which a 'better' code sequence exists depending +// on arguments should also go in here. + +class MacroAssembler: public Assembler { + + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) { + } + virtual ~MacroAssembler() {} + + void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod); + + // Place a fence.i after code may have been modified due to a safepoint. + void safepoint_ifence(); + + // Alignment + void align(int modulus, int extra_offset = 0); + + // Stack frame creation/removal + // Note that SP must be updated to the right place before saving/restoring RA and FP + // because signal based thread suspend/resume could happen asynchronously. + void enter() { + addi(sp, sp, - 2 * wordSize); + sd(ra, Address(sp, wordSize)); + sd(fp, Address(sp)); + addi(fp, sp, 2 * wordSize); + } + + void leave() { + addi(sp, fp, - 2 * wordSize); + ld(fp, Address(sp)); + ld(ra, Address(sp, wordSize)); + addi(sp, sp, 2 * wordSize); + } + + + // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) + // The pointer will be loaded into the thread register. + void get_thread(Register thread); + + // Support for VM calls + // + // It is imperative that all calls into the VM are handled via the call_VM macros. + // They make sure that the stack linkage is setup correctly. call_VM's correspond + // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. + + void call_VM(Register oop_result, + address entry_point, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, Register arg_2, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, Register arg_2, Register arg_3, + bool check_exceptions = true); + + // Overloadings with last_Java_sp + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments = 0, + bool check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + bool check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, Register arg_2, + bool check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, Register arg_2, Register arg_3, + bool check_exceptions = true); + + void get_vm_result(Register oop_result, Register java_thread); + void get_vm_result_2(Register metadata_result, Register java_thread); + + // These always tightly bind to MacroAssembler::call_VM_leaf_base + // bypassing the virtual implementation + void call_VM_leaf(address entry_point, + int number_of_arguments = 0); + void call_VM_leaf(address entry_point, + Register arg_0); + void call_VM_leaf(address entry_point, + Register arg_0, Register arg_1); + void call_VM_leaf(address entry_point, + Register arg_0, Register arg_1, Register arg_2); + + // These always tightly bind to MacroAssembler::call_VM_base + // bypassing the virtual implementation + void super_call_VM_leaf(address entry_point, Register arg_0); + void super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1); + void super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2); + void super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3); + + // last Java Frame (fills frame anchor) + void set_last_Java_frame(Register last_java_sp, Register last_java_fp, address last_java_pc, Register tmp); + void set_last_Java_frame(Register last_java_sp, Register last_java_fp, Label &last_java_pc, Register tmp); + void set_last_Java_frame(Register last_java_sp, Register last_java_fp, Register last_java_pc, Register tmp); + + // thread in the default location (xthread) + void reset_last_Java_frame(bool clear_fp); + + void call_native(address entry_point, + Register arg_0); + void call_native_base( + address entry_point, // the entry point + Label* retaddr = NULL + ); + + virtual void call_VM_leaf_base( + address entry_point, // the entry point + int number_of_arguments, // the number of arguments to pop after the call + Label* retaddr = NULL + ); + + virtual void call_VM_leaf_base( + address entry_point, // the entry point + int number_of_arguments, // the number of arguments to pop after the call + Label& retaddr) { + call_VM_leaf_base(entry_point, number_of_arguments, &retaddr); + } + + virtual void call_VM_base( // returns the register containing the thread upon return + Register oop_result, // where an oop-result ends up if any; use noreg otherwise + Register java_thread, // the thread if computed before ; use noreg otherwise + Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise + address entry_point, // the entry point + int number_of_arguments, // the number of arguments (w/o thread) to pop after the call + bool check_exceptions // whether to check for pending exceptions after return + ); + + void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); + + virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(Register java_thread); + + void resolve_weak_handle(Register result, Register tmp); + void resolve_oop_handle(Register result, Register tmp = x15); + void resolve_jobject(Register value, Register thread, Register tmp); + + void movoop(Register dst, jobject obj, bool immediate = false); + void mov_metadata(Register dst, Metadata* obj); + void bang_stack_size(Register size, Register tmp); + void set_narrow_oop(Register dst, jobject obj); + void set_narrow_klass(Register dst, Klass* k); + + void load_mirror(Register dst, Register method, Register tmp = x15); + 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 thread_tmp); + void load_klass(Register dst, Register src); + void store_klass(Register dst, Register src); + void cmp_klass(Register oop, Register trial_klass, Register tmp, Label &L); + + void encode_klass_not_null(Register r); + void decode_klass_not_null(Register r); + void encode_klass_not_null(Register dst, Register src, Register tmp = xheapbase); + void decode_klass_not_null(Register dst, Register src, Register tmp = xheapbase); + void decode_heap_oop_not_null(Register r); + void decode_heap_oop_not_null(Register dst, Register src); + void decode_heap_oop(Register d, Register s); + void decode_heap_oop(Register r) { decode_heap_oop(r, r); } + void encode_heap_oop(Register d, Register s); + void encode_heap_oop(Register r) { encode_heap_oop(r, r); }; + 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 thread_tmp = noreg, DecoratorSet decorators = 0); + + void store_klass_gap(Register dst, Register src); + + // currently unimplemented + // Used for storing NULL. All other oop constants should be + // stored using routines that take a jobject. + void store_heap_oop_null(Address dst); + + // This dummy is to prevent a call to store_heap_oop from + // converting a zero (linke NULL) into a Register by giving + // the compiler two choices it can't resolve + + void store_heap_oop(Address dst, void* dummy); + + // Support for NULL-checks + // + // Generates code that causes a NULL OS exception if the content of reg is NULL. + // If the accessed location is M[reg + offset] and the offset is known, provide the + // offset. No explicit code generateion is needed if the offset is within a certain + // range (0 <= offset <= page_size). + + virtual void null_check(Register reg, int offset = -1); + static bool needs_explicit_null_check(intptr_t offset); + static bool uses_implicit_null_check(void* address); + + // idiv variant which deals with MINLONG as dividend and -1 as divisor + int corrected_idivl(Register result, Register rs1, Register rs2, + bool want_remainder); + int corrected_idivq(Register result, Register rs1, Register rs2, + bool want_remainder); + + // interface method calling + void lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_tmp, + Label& no_such_interface, + bool return_method = true); + + // virtual method calling + // n.n. x86 allows RegisterOrConstant for vtable_index + void lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result); + + // Form an addres from base + offset in Rd. Rd my or may not + // actually be used: you must use the Address that is returned. It + // is up to you to ensure that the shift provided mathces the size + // of your data. + Address form_address(Register Rd, Register base, long byte_offset); + + // allocation + void tlab_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + Label& slow_case, // continuation point of fast allocation fails + bool is_far = false + ); + + void eden_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp, // temp register + Label& slow_case, // continuation point if fast allocation fails + bool is_far = false + ); + + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except tmp_reg + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register tmp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + Register super_check_offset = noreg); + + // The reset of the type cehck; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The tmp1_reg and tmp2_reg can be noreg, if no temps are avaliable. + // Updates the sub's secondary super cache as necessary. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure); + + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register tmp_reg, + Label& L_success); + + Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); + + // only if +VerifyOops + void verify_oop(Register reg, const char* s = "broken oop"); + void verify_oop_addr(Address addr, const char* s = "broken oop addr"); + + void _verify_method_ptr(Register reg, const char* msg, const char* file, int line) {} + void _verify_klass_ptr(Register reg, const char* msg, const char* file, int line) {} + +#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) +#define verify_klass_ptr(reg) _verify_method_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) + + // A more convenient access to fence for our purposes + // We used four bit to indicate the read and write bits in the predecessors and successors, + // and extended i for r, o for w if UseConservativeFence enabled. + enum Membar_mask_bits { + StoreStore = 0b0101, // (pred = ow + succ = ow) + LoadStore = 0b1001, // (pred = ir + succ = ow) + StoreLoad = 0b0110, // (pred = ow + succ = ir) + LoadLoad = 0b1010, // (pred = ir + succ = ir) + AnyAny = LoadStore | StoreLoad // (pred = iorw + succ = iorw) + }; + + void membar(uint32_t order_constraint); + + static void membar_mask_to_pred_succ(uint32_t order_constraint, uint32_t& predecessor, uint32_t& successor) { + predecessor = (order_constraint >> 2) & 0x3; + successor = order_constraint & 0x3; + + // extend rw -> iorw: + // 01(w) -> 0101(ow) + // 10(r) -> 1010(ir) + // 11(rw)-> 1111(iorw) + if (UseConservativeFence) { + predecessor |= predecessor << 2; + successor |= successor << 2; + } + } + + static int pred_succ_to_membar_mask(uint32_t predecessor, uint32_t successor) { + return ((predecessor & 0x3) << 2) | (successor & 0x3); + } + + // prints msg, dumps registers and stops execution + void stop(const char* msg); + + static void debug64(char* msg, int64_t pc, int64_t regs[]); + + void unimplemented(const char* what = ""); + + void should_not_reach_here() { stop("should not reach here"); } + + static address target_addr_for_insn(address insn_addr); + + // Required platform-specific helpers for Label::patch_instructions. + // They _shadow_ the declarations in AbstractAssembler, which are undefined. + static int pd_patch_instruction_size(address branch, address target); + static void pd_patch_instruction(address branch, address target, const char* file = NULL, int line = 0) { + pd_patch_instruction_size(branch, target); + } + static address pd_call_destination(address branch) { + return target_addr_for_insn(branch); + } + + static int patch_oop(address insn_addr, address o); + address emit_trampoline_stub(int insts_call_instruction_offset, address target); + void emit_static_call_stub(); + + // The following 4 methods return the offset of the appropriate move instruction + + // Support for fast byte/short loading with zero extension (depending on particular CPU) + int load_unsigned_byte(Register dst, Address src); + int load_unsigned_short(Register dst, Address src); + + // Support for fast byte/short loading with sign extension (depending on particular CPU) + int load_signed_byte(Register dst, Address src); + int load_signed_short(Register dst, Address src); + + // Load and store values by size and signed-ness + void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg); + void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); + + public: + // Standard pseudoinstruction + void nop(); + void mv(Register Rd, Register Rs); + void notr(Register Rd, Register Rs); + void neg(Register Rd, Register Rs); + void negw(Register Rd, Register Rs); + void sext_w(Register Rd, Register Rs); + void zext_b(Register Rd, Register Rs); + void seqz(Register Rd, Register Rs); // set if = zero + void snez(Register Rd, Register Rs); // set if != zero + void sltz(Register Rd, Register Rs); // set if < zero + void sgtz(Register Rd, Register Rs); // set if > zero + + // Float pseudoinstruction + void fmv_s(FloatRegister Rd, FloatRegister Rs); + void fabs_s(FloatRegister Rd, FloatRegister Rs); // single-precision absolute value + void fneg_s(FloatRegister Rd, FloatRegister Rs); + + // Double pseudoinstruction + void fmv_d(FloatRegister Rd, FloatRegister Rs); + void fabs_d(FloatRegister Rd, FloatRegister Rs); + void fneg_d(FloatRegister Rd, FloatRegister Rs); + + // Pseudoinstruction for control and status register + void rdinstret(Register Rd); // read instruction-retired counter + void rdcycle(Register Rd); // read cycle counter + void rdtime(Register Rd); // read time + void csrr(Register Rd, unsigned csr); // read csr + void csrw(unsigned csr, Register Rs); // write csr + void csrs(unsigned csr, Register Rs); // set bits in csr + void csrc(unsigned csr, Register Rs); // clear bits in csr + void csrwi(unsigned csr, unsigned imm); + void csrsi(unsigned csr, unsigned imm); + void csrci(unsigned csr, unsigned imm); + void frcsr(Register Rd); // read float-point csr + void fscsr(Register Rd, Register Rs); // swap float-point csr + void fscsr(Register Rs); // write float-point csr + void frrm(Register Rd); // read float-point rounding mode + void fsrm(Register Rd, Register Rs); // swap float-point rounding mode + void fsrm(Register Rs); // write float-point rounding mode + void fsrmi(Register Rd, unsigned imm); + void fsrmi(unsigned imm); + void frflags(Register Rd); // read float-point exception flags + void fsflags(Register Rd, Register Rs); // swap float-point exception flags + void fsflags(Register Rs); // write float-point exception flags + void fsflagsi(Register Rd, unsigned imm); + void fsflagsi(unsigned imm); + + void beqz(Register Rs, const address &dest); + void bnez(Register Rs, const address &dest); + void blez(Register Rs, const address &dest); + void bgez(Register Rs, const address &dest); + void bltz(Register Rs, const address &dest); + void bgtz(Register Rs, const address &dest); + void la(Register Rd, Label &label); + void la(Register Rd, const address &dest); + void la(Register Rd, const Address &adr); + //label + void beqz(Register Rs, Label &l, bool is_far = false); + void bnez(Register Rs, Label &l, bool is_far = false); + void blez(Register Rs, Label &l, bool is_far = false); + void bgez(Register Rs, Label &l, bool is_far = false); + void bltz(Register Rs, Label &l, bool is_far = false); + void bgtz(Register Rs, Label &l, bool is_far = false); + void float_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void float_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void float_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void float_bge(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void float_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void float_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_bge(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + + void push_reg(RegSet regs, Register stack) { if (regs.bits()) { push_reg(regs.bits(), stack); } } + void pop_reg(RegSet regs, Register stack) { if (regs.bits()) { pop_reg(regs.bits(), stack); } } + void push_reg(Register Rs); + void pop_reg(Register Rd); + int push_reg(unsigned int bitset, Register stack); + int pop_reg(unsigned int bitset, Register stack); + 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); } +#ifdef COMPILER2 + void push_vp(VectorRegSet regs, Register stack) { if (regs.bits()) push_vp(regs.bits(), stack); } + void pop_vp(VectorRegSet regs, Register stack) { if (regs.bits()) pop_vp(regs.bits(), stack); } +#endif // COMPILER2 + + // Push and pop everything that might be clobbered by a native + // runtime call except t0 and t1. (They are always + // temporary registers, so we don't have to protect them.) + // Additional registers can be excluded in a passed RegSet. + void push_call_clobbered_registers_except(RegSet exclude); + void pop_call_clobbered_registers_except(RegSet exclude); + + void push_call_clobbered_registers() { + push_call_clobbered_registers_except(RegSet()); + } + void pop_call_clobbered_registers() { + pop_call_clobbered_registers_except(RegSet()); + } + + void pusha(); + void popa(); + void push_CPU_state(bool save_vectors = false, int vector_size_in_bytes = 0); + void pop_CPU_state(bool restore_vectors = false, int vector_size_in_bytes = 0); + + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); + + void bind(Label& L) { + Assembler::bind(L); + // fences across basic blocks should not be merged + code()->clear_last_insn(); + } + + // mv + template::value)> + inline void mv(Register Rd, T o) { + li(Rd, (int64_t)o); + } + + inline void mvw(Register Rd, int32_t imm32) { mv(Rd, imm32); } + + void mv(Register Rd, Address dest); + void mv(Register Rd, address addr); + void mv(Register Rd, RegisterOrConstant src); + + // logic + void andrw(Register Rd, Register Rs1, Register Rs2); + void orrw(Register Rd, Register Rs1, Register Rs2); + void xorrw(Register Rd, Register Rs1, Register Rs2); + + // revb + void revb_h_h(Register Rd, Register Rs, Register tmp = t0); // reverse bytes in halfword in lower 16 bits, sign-extend + void revb_w_w(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); // reverse bytes in lower word, sign-extend + void revb_h_h_u(Register Rd, Register Rs, Register tmp = t0); // reverse bytes in halfword in lower 16 bits, zero-extend + void revb_h_w_u(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); // reverse bytes in halfwords in lower 32 bits, zero-extend + void revb_h_helper(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2= t1); // reverse bytes in upper 16 bits (48:63) and move to lower + void revb_h(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2= t1); // reverse bytes in each halfword + void revb_w(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2= t1); // reverse bytes in each word + void revb(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); // reverse bytes in doubleword + + void ror_imm(Register dst, Register src, uint32_t shift, Register tmp = t0); + void andi(Register Rd, Register Rn, int64_t imm, Register tmp = t0); + void orptr(Address adr, RegisterOrConstant src, Register tmp1 = t0, Register tmp2 = t1); + + void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, Label &succeed, Label *fail); + void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail); + void cmpxchg(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, bool result_as_bool = false); + void cmpxchg_weak(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result); + void cmpxchg_narrow_value_helper(Register addr, Register expected, + Register new_val, + enum operand_size size, + Register tmp1, Register tmp2, Register tmp3); + void cmpxchg_narrow_value(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, bool result_as_bool, + Register tmp1, Register tmp2, Register tmp3); + void weak_cmpxchg_narrow_value(Register addr, Register expected, + Register new_val, + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result, + Register tmp1, Register tmp2, Register tmp3); + + void atomic_add(Register prev, RegisterOrConstant incr, Register addr); + void atomic_addw(Register prev, RegisterOrConstant incr, Register addr); + void atomic_addal(Register prev, RegisterOrConstant incr, Register addr); + void atomic_addalw(Register prev, RegisterOrConstant incr, Register addr); + + void atomic_xchg(Register prev, Register newv, Register addr); + void atomic_xchgw(Register prev, Register newv, Register addr); + void atomic_xchgal(Register prev, Register newv, Register addr); + void atomic_xchgalw(Register prev, Register newv, Register addr); + void atomic_xchgwu(Register prev, Register newv, Register addr); + void atomic_xchgalwu(Register prev, Register newv, Register addr); + + static bool far_branches() { + return ReservedCodeCacheSize > branch_range; + } + + // Jumps that can reach anywhere in the code cache. + // Trashes tmp. + void far_call(Address entry, CodeBuffer *cbuf = NULL, Register tmp = t0); + void far_jump(Address entry, CodeBuffer *cbuf = NULL, Register tmp = t0); + + static int far_branch_size() { + if (far_branches()) { + return 2 * 4; // auipc + jalr, see far_call() & far_jump() + } else { + return 4; + } + } + + void load_byte_map_base(Register reg); + + void bang_stack_with_offset(int offset) { + // stack grows down, caller passes positive offset + assert(offset > 0, "must bang with negative offset"); + sub(t0, sp, offset); + sd(zr, Address(t0)); + } + + void la_patchable(Register reg1, const Address &dest, int32_t &offset); + + virtual void _call_Unimplemented(address call_site) { + mv(t1, call_site); + } + + #define call_Unimplemented() _call_Unimplemented((address)__PRETTY_FUNCTION__) + + // Frame creation and destruction shared between JITs. + void build_frame(int framesize); + void remove_frame(int framesize); + + void reserved_stack_check(); + + void get_polling_page(Register dest, relocInfo::relocType rtype); + address read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); + + address trampoline_call(Address entry, CodeBuffer* cbuf = NULL); + address ic_call(address entry, jint method_index = 0); + + void add_memory_int64(const Address dst, int64_t imm); + void add_memory_int32(const Address dst, int32_t imm); + + void cmpptr(Register src1, Address src2, Label& equal); + + void clinit_barrier(Register klass, Register tmp, Label* L_fast_path = NULL, Label* L_slow_path = NULL); + void load_method_holder_cld(Register result, Register method); + void load_method_holder(Register holder, Register method); + + void compute_index(Register str1, Register trailing_zeros, Register match_mask, + Register result, Register char_tmp, Register tmp, + bool haystack_isL); + void compute_match_mask(Register src, Register pattern, Register match_mask, + Register mask1, Register mask2); + +#ifdef COMPILER2 + void mul_add(Register out, Register in, Register offset, + Register len, Register k, Register tmp); + void cad(Register dst, Register src1, Register src2, Register carry); + void cadc(Register dst, Register src1, Register src2, Register carry); + void adc(Register dst, Register src1, Register src2, Register carry); + void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo, + Register src1, Register src2, Register carry); + void multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, + Register y, Register y_idx, Register z, + Register carry, Register product, + Register idx, Register kdx); + void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, + Register y, Register y_idx, Register z, + Register carry, Register product, + Register idx, Register kdx); + void multiply_128_x_128_loop(Register y, Register z, + Register carry, Register carry2, + Register idx, Register jdx, + Register yz_idx1, Register yz_idx2, + Register tmp, Register tmp3, Register tmp4, + Register tmp6, Register product_hi); + void multiply_to_len(Register x, Register xlen, Register y, Register ylen, + Register z, Register zlen, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, + Register tmp5, Register tmp6, Register product_hi); +#endif + + void inflate_lo32(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); + void inflate_hi32(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); + + void ctzc_bit(Register Rd, Register Rs, bool isLL = false, Register tmp1 = t0, Register tmp2 = t1); + + void zero_words(Register base, u_int64_t cnt); + address zero_words(Register ptr, Register cnt); + void fill_words(Register base, Register cnt, Register value); + void zero_memory(Register addr, Register len, Register tmp); + + // shift left by shamt and add + void shadd(Register Rd, Register Rs1, Register Rs2, Register tmp, int shamt); + + // Here the float instructions with safe deal with some exceptions. + // e.g. convert from NaN, +Inf, -Inf to int, float, double + // will trigger exception, we need to deal with these situations + // to get correct results. + void fcvt_w_s_safe(Register dst, FloatRegister src, Register tmp = t0); + void fcvt_l_s_safe(Register dst, FloatRegister src, Register tmp = t0); + void fcvt_w_d_safe(Register dst, FloatRegister src, Register tmp = t0); + void fcvt_l_d_safe(Register dst, FloatRegister src, Register tmp = t0); + + // vector load/store unit-stride instructions + void vlex_v(VectorRegister vd, Register base, Assembler::SEW sew, VectorMask vm = unmasked) { + switch (sew) { + case Assembler::e64: + vle64_v(vd, base, vm); + break; + case Assembler::e32: + vle32_v(vd, base, vm); + break; + case Assembler::e16: + vle16_v(vd, base, vm); + break; + case Assembler::e8: // fall through + default: + vle8_v(vd, base, vm); + break; + } + } + + void vsex_v(VectorRegister store_data, Register base, Assembler::SEW sew, VectorMask vm = unmasked) { + switch (sew) { + case Assembler::e64: + vse64_v(store_data, base, vm); + break; + case Assembler::e32: + vse32_v(store_data, base, vm); + break; + case Assembler::e16: + vse16_v(store_data, base, vm); + break; + case Assembler::e8: // fall through + default: + vse8_v(store_data, base, vm); + break; + } + } + + static const int zero_words_block_size; + + void cast_primitive_type(BasicType type, Register Rt) { + switch (type) { + case T_BOOLEAN: + sltu(Rt, zr, Rt); + break; + case T_CHAR : + zero_extend(Rt, Rt, 16); + break; + case T_BYTE : + sign_extend(Rt, Rt, 8); + break; + case T_SHORT : + sign_extend(Rt, Rt, 16); + break; + case T_INT : + addw(Rt, Rt, zr); + break; + case T_LONG : /* nothing to do */ break; + case T_VOID : /* nothing to do */ break; + case T_FLOAT : /* nothing to do */ break; + case T_DOUBLE : /* nothing to do */ break; + default: ShouldNotReachHere(); + } + } + + // float cmp with unordered_result + void float_compare(Register result, FloatRegister Rs1, FloatRegister Rs2, int unordered_result); + void double_compare(Register result, FloatRegister Rs1, FloatRegister Rs2, int unordered_result); + + // Zero/Sign-extend + void zero_extend(Register dst, Register src, int bits); + void sign_extend(Register dst, Register src, int bits); + + // compare src1 and src2 and get -1/0/1 in dst. + // if [src1 > src2], dst = 1; + // if [src1 == src2], dst = 0; + // if [src1 < src2], dst = -1; + void cmp_l2i(Register dst, Register src1, Register src2, Register tmp = t0); + + int push_fp(unsigned int bitset, Register stack); + int pop_fp(unsigned int bitset, Register stack); + + int push_vp(unsigned int bitset, Register stack); + int pop_vp(unsigned int bitset, Register stack); + + // vext + void vmnot_m(VectorRegister vd, VectorRegister vs); + void vncvt_x_x_w(VectorRegister vd, VectorRegister vs, VectorMask vm = unmasked); + void vfneg_v(VectorRegister vd, VectorRegister vs); + +private: + +#ifdef ASSERT + // Template short-hand support to clean-up after a failed call to trampoline + // call generation (see trampoline_call() below), when a set of Labels must + // be reset (before returning). + template + void reset_labels(Label& lbl, More&... more) { + lbl.reset(); reset_labels(more...); + } + template + void reset_labels(Label& lbl) { + lbl.reset(); + } +#endif + void repne_scan(Register addr, Register value, Register count, Register tmp); + + // Return true if an address is within the 48-bit RISCV64 address space. + bool is_valid_riscv64_address(address addr) { + return ((uintptr_t)addr >> 48) == 0; + } + + void ld_constant(Register dest, const Address &const_addr) { + if (NearCpool) { + ld(dest, const_addr); + } else { + int32_t offset = 0; + la_patchable(dest, InternalAddress(const_addr.target()), offset); + ld(dest, Address(dest, offset)); + } + } + + int bitset_to_regs(unsigned int bitset, unsigned char* regs); + Address add_memory_helper(const Address dst); + + void load_reserved(Register addr, enum operand_size size, Assembler::Aqrl acquire); + void store_conditional(Register addr, Register new_val, enum operand_size size, Assembler::Aqrl release); + + // Check the current thread doesn't need a cross modify fence. + void verify_cross_modify_fence_not_required() PRODUCT_RETURN; +}; + +#ifdef ASSERT +inline bool AbstractAssembler::pd_check_instruction_mark() { return false; } +#endif + +/** + * class SkipIfEqual: + * + * Instantiating this class will result in assembly code being output that will + * jump around any code emitted between the creation of the instance and it's + * automatic destruction at the end of a scope block, depending on the value of + * the flag passed to the constructor, which will be checked at run-time. + */ +class SkipIfEqual { + private: + MacroAssembler* _masm; + Label _label; + + public: + SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value); + ~SkipIfEqual(); +}; + +#endif // CPU_RISCV_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ef968ccd96d98b42916980d78a78bbb73e8e8ddf --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_MACROASSEMBLER_RISCV_INLINE_HPP +#define CPU_RISCV_MACROASSEMBLER_RISCV_INLINE_HPP + +// Still empty. + +#endif // CPU_RISCV_MACROASSEMBLER_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..23a75d20502609871250ede91d637c8f206ef4e2 --- /dev/null +++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_MATCHER_RISCV_HPP +#define CPU_RISCV_MATCHER_RISCV_HPP + + // Defined within class Matcher + + // false => size gets scaled to BytesPerLong, ok. + static const bool init_array_count_is_in_bytes = false; + + // Whether this platform implements the scalable vector feature + static const bool implements_scalable_vector = true; + + static const bool supports_scalable_vector() { + return UseRVV; + } + + // riscv supports misaligned vectors store/load. + static constexpr bool misaligned_vectors_ok() { + return true; + } + + // Whether code generation need accurate ConvI2L types. + static const bool convi2l_type_required = false; + + // Does the CPU require late expand (see block.cpp for description of late expand)? + static const bool require_postalloc_expand = false; + + // Do we need to mask the count passed to shift instructions or does + // the cpu only look at the lower 5/6 bits anyway? + static const bool need_masked_shift_count = false; + + // No support for generic vector operands. + static const bool supports_generic_vector_operands = false; + + static constexpr bool isSimpleConstant64(jlong value) { + // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. + // Probably always true, even if a temp register is required. + return true; + } + + // Use conditional move (CMOVL) + static constexpr int long_cmove_cost() { + // long cmoves are no more expensive than int cmoves + return 0; + } + + static constexpr int float_cmove_cost() { + // float cmoves are no more expensive than int cmoves + return 0; + } + + // This affects two different things: + // - how Decode nodes are matched + // - how ImplicitNullCheck opportunities are recognized + // If true, the matcher will try to remove all Decodes and match them + // (as operands) into nodes. NullChecks are not prepared to deal with + // Decodes by final_graph_reshaping(). + // If false, final_graph_reshaping() forces the decode behind the Cmp + // for a NullCheck. The matcher matches the Decode node into a register. + // Implicit_null_check optimization moves the Decode along with the + // memory operation back up before the NullCheck. + static bool narrow_oop_use_complex_address() { + return CompressedOops::shift() == 0; + } + + static bool narrow_klass_use_complex_address() { + return false; + } + + static bool const_oop_prefer_decode() { + // Prefer ConN+DecodeN over ConP in simple compressed oops mode. + return CompressedOops::base() == NULL; + } + + static bool const_klass_prefer_decode() { + // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. + return CompressedKlassPointers::base() == NULL; + } + + // Is it better to copy float constants, or load them directly from + // memory? Intel can load a float constant from a direct address, + // requiring no extra registers. Most RISCs will have to materialize + // an address into a register first, so they would do better to copy + // the constant from stack. + static const bool rematerialize_float_constants = false; + + // If CPU can load and store mis-aligned doubles directly then no + // fixup is needed. Else we split the double into 2 integer pieces + // and move it piece-by-piece. Only happens when passing doubles into + // C code as the Java calling convention forces doubles to be aligned. + static const bool misaligned_doubles_ok = true; + + // Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. + static const bool strict_fp_requires_explicit_rounding = false; + + // Are floats converted to double when stored to stack during + // deoptimization? + static constexpr bool float_in_double() { return false; } + + // Do ints take an entire long register or just half? + // The relevant question is how the int is callee-saved: + // the whole long is written but de-opt'ing will have to extract + // the relevant 32 bits. + static const bool int_in_long = true; + + // Does the CPU supports vector variable shift instructions? + static constexpr bool supports_vector_variable_shifts(void) { + return false; + } + + // Does the CPU supports vector variable rotate instructions? + static constexpr bool supports_vector_variable_rotates(void) { + return false; + } + + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return false; + } + + // Does the CPU supports vector unsigned comparison instructions? + static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { + return false; + } + + // Some microarchitectures have mask registers used on vectors + static const bool has_predicated_vectors(void) { + return false; + } + + // true means we have fast l2f convers + // false means that conversion is done by runtime call + static constexpr bool convL2FSupported(void) { + return true; + } + + // Implements a variant of EncodeISOArrayNode that encode ASCII only + static const bool supports_encode_ascii_array = false; + + // 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_RISCV_MATCHER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f7c0c87c216da57fcbf35ba4da78b031ca84f03 --- /dev/null +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp @@ -0,0 +1,461 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "classfile/javaClasses.inline.hpp" +#include "classfile/vmClasses.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/flags/flagSetting.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/stubRoutines.hpp" + +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) { + assert_cond(_masm != NULL); + if (VerifyMethodHandles) { + verify_klass(_masm, klass_reg, VM_CLASS_ID(java_lang_Class), + "MH argument is a Class"); + } + __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset())); +} + +#ifdef ASSERT +static int check_nonzero(const char* xname, int x) { + assert(x != 0, "%s should be nonzero", xname); + return x; +} +#define NONZERO(x) check_nonzero(#x, x) +#else //ASSERT +#define NONZERO(x) (x) +#endif //PRODUCT + +#ifdef ASSERT +void MethodHandles::verify_klass(MacroAssembler* _masm, + Register obj, vmClassID klass_id, + const char* error_message) { + assert_cond(_masm != NULL); + InstanceKlass** klass_addr = vmClasses::klass_addr_at(klass_id); + Klass* klass = vmClasses::klass_at(klass_id); + Register temp = t1; + Register temp2 = t0; // used by MacroAssembler::cmpptr + Label L_ok, L_bad; + BLOCK_COMMENT("verify_klass {"); + __ verify_oop(obj); + __ beqz(obj, L_bad); + __ push_reg(RegSet::of(temp, temp2), sp); + __ load_klass(temp, obj); + __ cmpptr(temp, ExternalAddress((address) klass_addr), L_ok); + intptr_t super_check_offset = klass->super_check_offset(); + __ ld(temp, Address(temp, super_check_offset)); + __ cmpptr(temp, ExternalAddress((address) klass_addr), L_ok); + __ pop_reg(RegSet::of(temp, temp2), sp); + __ bind(L_bad); + __ stop(error_message); + __ BIND(L_ok); + __ pop_reg(RegSet::of(temp, temp2), sp); + BLOCK_COMMENT("} verify_klass"); +} + +void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) {} + +#endif //ASSERT + +void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, + bool for_compiler_entry) { + assert_cond(_masm != NULL); + assert(method == xmethod, "interpreter calling convention"); + Label L_no_such_method; + __ beqz(xmethod, L_no_such_method); + __ verify_method_ptr(method); + + if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { + Label run_compiled_code; + // JVMTI events, such as single-stepping, are implemented partly by avoiding running + // compiled code in threads for which the event is enabled. Check here for + // interp_only_mode if these events CAN be enabled. + + __ lwu(t0, Address(xthread, JavaThread::interp_only_mode_offset())); + __ beqz(t0, run_compiled_code); + __ ld(t0, Address(method, Method::interpreter_entry_offset())); + __ jr(t0); + __ BIND(run_compiled_code); + } + + const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : + Method::from_interpreted_offset(); + __ ld(t0,Address(method, entry_offset)); + __ jr(t0); + __ bind(L_no_such_method); + __ far_jump(RuntimeAddress(StubRoutines::throw_AbstractMethodError_entry())); +} + +void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, + Register recv, Register method_temp, + Register temp2, + bool for_compiler_entry) { + assert_cond(_masm != NULL); + BLOCK_COMMENT("jump_to_lambda_form {"); + // This is the initial entry point of a lazy method handle. + // After type checking, it picks up the invoker from the LambdaForm. + assert_different_registers(recv, method_temp, temp2); + assert(recv != noreg, "required register"); + assert(method_temp == xmethod, "required register for loading method"); + + // Load the invoker, as MH -> MH.form -> LF.vmentry + __ verify_oop(recv); + __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset())), temp2); + __ verify_oop(method_temp); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset())), temp2); + __ verify_oop(method_temp); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset())), temp2); + __ verify_oop(method_temp); + __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())), noreg, noreg); + + if (VerifyMethodHandles && !for_compiler_entry) { + // make sure recv is already on stack + __ ld(temp2, Address(method_temp, Method::const_offset())); + __ load_sized_value(temp2, + Address(temp2, ConstMethod::size_of_parameters_offset()), + sizeof(u2), /*is_signed*/ false); + Label L; + __ ld(t0, __ argument_address(temp2, -1)); + __ beq(recv, t0, L); + __ ld(x10, __ argument_address(temp2, -1)); + __ ebreak(); + __ BIND(L); + } + + jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry); + BLOCK_COMMENT("} jump_to_lambda_form"); +} + +// Code generation +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm, + vmIntrinsics::ID iid) { + assert_cond(_masm != NULL); + const bool not_for_compiler_entry = false; // this is the interpreter entry + assert(is_signature_polymorphic(iid), "expected invoke iid"); + if (iid == vmIntrinsics::_invokeGeneric || + iid == vmIntrinsics::_compiledLambdaForm) { + // Perhaps surprisingly, the symbolic references visible to Java are not directly used. + // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod. + // They all allow an appendix argument. + __ ebreak(); // empty stubs make SG sick + return NULL; + } + + // No need in interpreter entry for linkToNative for now. + // Interpreter calls compiled entry through i2c. + if (iid == vmIntrinsics::_linkToNative) { + __ ebreak(); + return NULL; + } + + // x30: sender SP (must preserve; see prepare_to_jump_from_interpreted) + // xmethod: Method* + // x13: argument locator (parameter slot count, added to sp) + // x11: used as temp to hold mh or receiver + // x10, x29: garbage temps, blown away + Register argp = x13; // argument list ptr, live on error paths + Register mh = x11; // MH receiver; dies quickly and is recycled + + // here's where control starts out: + __ align(CodeEntryAlignment); + address entry_point = __ pc(); + + if (VerifyMethodHandles) { + assert(Method::intrinsic_id_size_in_bytes() == 2, "assuming Method::_intrinsic_id is u2"); + + Label L; + BLOCK_COMMENT("verify_intrinsic_id {"); + __ lhu(t0, Address(xmethod, Method::intrinsic_id_offset_in_bytes())); + __ mv(t1, (int) iid); + __ beq(t0, t1, L); + if (iid == vmIntrinsics::_linkToVirtual || + iid == vmIntrinsics::_linkToSpecial) { + // could do this for all kinds, but would explode assembly code size + trace_method_handle(_masm, "bad Method*::intrinsic_id"); + } + __ ebreak(); + __ bind(L); + BLOCK_COMMENT("} verify_intrinsic_id"); + } + + // First task: Find out how big the argument list is. + Address x13_first_arg_addr; + int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid); + assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic"); + if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) { + __ ld(argp, Address(xmethod, Method::const_offset())); + __ load_sized_value(argp, + Address(argp, ConstMethod::size_of_parameters_offset()), + sizeof(u2), /*is_signed*/ false); + x13_first_arg_addr = __ argument_address(argp, -1); + } else { + DEBUG_ONLY(argp = noreg); + } + + if (!is_signature_polymorphic_static(iid)) { + __ ld(mh, x13_first_arg_addr); + DEBUG_ONLY(argp = noreg); + } + + // x13_first_arg_addr is live! + + trace_method_handle_interpreter_entry(_masm, iid); + if (iid == vmIntrinsics::_invokeBasic) { + generate_method_handle_dispatch(_masm, iid, mh, noreg, not_for_compiler_entry); + } else { + // Adjust argument list by popping the trailing MemberName argument. + Register recv = noreg; + if (MethodHandles::ref_kind_has_receiver(ref_kind)) { + // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack. + __ ld(recv = x12, x13_first_arg_addr); + } + DEBUG_ONLY(argp = noreg); + Register xmember = xmethod; // MemberName ptr; incoming method ptr is dead now + __ pop_reg(xmember); // extract last argument + generate_method_handle_dispatch(_masm, iid, recv, xmember, not_for_compiler_entry); + } + + return entry_point; +} + + +void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, + vmIntrinsics::ID iid, + Register receiver_reg, + Register member_reg, + bool for_compiler_entry) { + assert_cond(_masm != NULL); + assert(is_signature_polymorphic(iid), "expected invoke iid"); + // temps used in this code are not used in *either* compiled or interpreted calling sequences + Register temp1 = x7; + Register temp2 = x28; + Register temp3 = x29; // x30 is live by this point: it contains the sender SP + if (for_compiler_entry) { + assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment"); + assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); + assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); + assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); + } + + assert_different_registers(temp1, temp2, temp3, receiver_reg); + assert_different_registers(temp1, temp2, temp3, member_reg); + + if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { + if (iid == vmIntrinsics::_linkToNative) { + assert(for_compiler_entry, "only compiler entry is supported"); + } + // indirect through MH.form.vmentry.vmtarget + jump_to_lambda_form(_masm, receiver_reg, xmethod, temp1, for_compiler_entry); + } else { + // The method is a member invoker used by direct method handles. + if (VerifyMethodHandles) { + // make sure the trailing argument really is a MemberName (caller responsibility) + verify_klass(_masm, member_reg, VM_CLASS_ID(java_lang_invoke_MemberName), + "MemberName required for invokeVirtual etc."); + } + + Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset())); + Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset())); + Address vmtarget_method( xmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())); + + Register temp1_recv_klass = temp1; + if (iid != vmIntrinsics::_linkToStatic) { + __ verify_oop(receiver_reg); + if (iid == vmIntrinsics::_linkToSpecial) { + // Don't actually load the klass; just null-check the receiver. + __ null_check(receiver_reg); + } else { + // load receiver klass itself + __ null_check(receiver_reg, oopDesc::klass_offset_in_bytes()); + __ load_klass(temp1_recv_klass, receiver_reg); + __ verify_klass_ptr(temp1_recv_klass); + } + BLOCK_COMMENT("check_receiver {"); + // The receiver for the MemberName must be in receiver_reg. + // Check the receiver against the MemberName.clazz + if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) { + // Did not load it above... + __ load_klass(temp1_recv_klass, receiver_reg); + __ verify_klass_ptr(temp1_recv_klass); + } + if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) { + Label L_ok; + Register temp2_defc = temp2; + __ load_heap_oop(temp2_defc, member_clazz, temp3); + load_klass_from_Class(_masm, temp2_defc); + __ verify_klass_ptr(temp2_defc); + __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, L_ok); + // If we get here, the type check failed! + __ ebreak(); + __ bind(L_ok); + } + BLOCK_COMMENT("} check_receiver"); + } + if (iid == vmIntrinsics::_linkToSpecial || + iid == vmIntrinsics::_linkToStatic) { + DEBUG_ONLY(temp1_recv_klass = noreg); // these guys didn't load the recv_klass + } + + // Live registers at this point: + // member_reg - MemberName that was the trailing argument + // temp1_recv_klass - klass of stacked receiver, if needed + // x30 - interpreter linkage (if interpreted) + // x11 ... x10 - compiler arguments (if compiled) + + Label L_incompatible_class_change_error; + switch (iid) { + case vmIntrinsics::_linkToSpecial: + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); + } + __ load_heap_oop(xmethod, member_vmtarget); + __ access_load_at(T_ADDRESS, IN_HEAP, xmethod, vmtarget_method, noreg, noreg); + break; + + case vmIntrinsics::_linkToStatic: + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); + } + __ load_heap_oop(xmethod, member_vmtarget); + __ access_load_at(T_ADDRESS, IN_HEAP, xmethod, vmtarget_method, noreg, noreg); + break; + + case vmIntrinsics::_linkToVirtual: + { + // same as TemplateTable::invokevirtual, + // minus the CP setup and profiling: + + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3); + } + + // pick out the vtable index from the MemberName, and then we can discard it: + Register temp2_index = temp2; + __ access_load_at(T_ADDRESS, IN_HEAP, temp2_index, member_vmindex, noreg, noreg); + + if (VerifyMethodHandles) { + Label L_index_ok; + __ bgez(temp2_index, L_index_ok); + __ ebreak(); + __ BIND(L_index_ok); + } + + // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget + // at this point. And VerifyMethodHandles has already checked clazz, if needed. + + // get target Method* & entry point + __ lookup_virtual_method(temp1_recv_klass, temp2_index, xmethod); + break; + } + + case vmIntrinsics::_linkToInterface: + { + // same as TemplateTable::invokeinterface + // (minus the CP setup and profiling, with different argument motion) + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3); + } + + Register temp3_intf = temp3; + __ load_heap_oop(temp3_intf, member_clazz); + load_klass_from_Class(_masm, temp3_intf); + __ verify_klass_ptr(temp3_intf); + + Register rindex = xmethod; + __ access_load_at(T_ADDRESS, IN_HEAP, rindex, member_vmindex, noreg, noreg); + if (VerifyMethodHandles) { + Label L; + __ bgez(rindex, L); + __ ebreak(); + __ bind(L); + } + + // given intf, index, and recv klass, dispatch to the implementation method + __ lookup_interface_method(temp1_recv_klass, temp3_intf, + // note: next two args must be the same: + rindex, xmethod, + temp2, + L_incompatible_class_change_error); + break; + } + + default: + fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid)); + break; + } + + // live at this point: xmethod, x30 (if interpreted) + + // After figuring out which concrete method to call, jump into it. + // Note that this works in the interpreter with no data motion. + // But the compiled version will require that r2_recv be shifted out. + __ verify_method_ptr(xmethod); + jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry); + if (iid == vmIntrinsics::_linkToInterface) { + __ bind(L_incompatible_class_change_error); + __ far_jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); + } + } + +} + +#ifndef PRODUCT +void trace_method_handle_stub(const char* adaptername, + oopDesc* mh, + intptr_t* saved_regs, + intptr_t* entry_sp) { } + +// The stub wraps the arguments in a struct on the stack to avoid +// dealing with the different calling conventions for passing 6 +// arguments. +struct MethodHandleStubArguments { + const char* adaptername; + oopDesc* mh; + intptr_t* saved_regs; + intptr_t* entry_sp; +}; +void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) { } + +void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { } +#endif //PRODUCT diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f73aba29d6750db8693eecd8100e5f2d1e85fc08 --- /dev/null +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// Platform-specific definitions for method handles. +// These definitions are inlined into class MethodHandles. + +// Adapters +enum /* platform_dependent_constants */ { + adapter_code_size = 32000 DEBUG_ONLY(+ 120000) +}; + +public: + + static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg); + + static void verify_klass(MacroAssembler* _masm, + Register obj, vmClassID klass_id, + const char* error_message = "wrong klass") NOT_DEBUG_RETURN; + + static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { + verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle), + "reference is a MH"); + } + + static void verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) NOT_DEBUG_RETURN; + + // Similar to InterpreterMacroAssembler::jump_from_interpreted. + // Takes care of special dispatch from single stepping too. + static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, + bool for_compiler_entry); + + static void jump_to_lambda_form(MacroAssembler* _masm, + Register recv, Register method_temp, + Register temp2, + bool for_compiler_entry); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a05c5778607fb8e4cc6cba503db584197fe7537 --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "code/compiledIC.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/handles.hpp" +#include "runtime/orderAccess.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/ostream.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif + +Register NativeInstruction::extract_rs1(address instr) { + assert_cond(instr != NULL); + return as_Register(Assembler::extract(((unsigned*)instr)[0], 19, 15)); +} + +Register NativeInstruction::extract_rs2(address instr) { + assert_cond(instr != NULL); + return as_Register(Assembler::extract(((unsigned*)instr)[0], 24, 20)); +} + +Register NativeInstruction::extract_rd(address instr) { + assert_cond(instr != NULL); + return as_Register(Assembler::extract(((unsigned*)instr)[0], 11, 7)); +} + +uint32_t NativeInstruction::extract_opcode(address instr) { + assert_cond(instr != NULL); + return Assembler::extract(((unsigned*)instr)[0], 6, 0); +} + +uint32_t NativeInstruction::extract_funct3(address instr) { + assert_cond(instr != NULL); + return Assembler::extract(((unsigned*)instr)[0], 14, 12); +} + +bool NativeInstruction::is_pc_relative_at(address instr) { + // auipc + jalr + // auipc + addi + // auipc + load + // auipc + fload_load + return (is_auipc_at(instr)) && + (is_addi_at(instr + instruction_size) || + is_jalr_at(instr + instruction_size) || + is_load_at(instr + instruction_size) || + is_float_load_at(instr + instruction_size)) && + check_pc_relative_data_dependency(instr); +} + +// ie:ld(Rd, Label) +bool NativeInstruction::is_load_pc_relative_at(address instr) { + return is_auipc_at(instr) && // auipc + is_ld_at(instr + instruction_size) && // ld + check_load_pc_relative_data_dependency(instr); +} + +bool NativeInstruction::is_movptr_at(address instr) { + return is_lui_at(instr) && // Lui + is_addi_at(instr + instruction_size) && // Addi + is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 + is_addi_at(instr + instruction_size * 3) && // Addi + is_slli_shift_at(instr + instruction_size * 4, 5) && // Slli Rd, Rs, 5 + (is_addi_at(instr + instruction_size * 5) || + is_jalr_at(instr + instruction_size * 5) || + is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load + check_movptr_data_dependency(instr); +} + +bool NativeInstruction::is_li32_at(address instr) { + return is_lui_at(instr) && // lui + is_addiw_at(instr + instruction_size) && // addiw + check_li32_data_dependency(instr); +} + +bool NativeInstruction::is_li64_at(address instr) { + return is_lui_at(instr) && // lui + is_addi_at(instr + instruction_size) && // addi + is_slli_shift_at(instr + instruction_size * 2, 12) && // Slli Rd, Rs, 12 + is_addi_at(instr + instruction_size * 3) && // addi + is_slli_shift_at(instr + instruction_size * 4, 12) && // Slli Rd, Rs, 12 + is_addi_at(instr + instruction_size * 5) && // addi + is_slli_shift_at(instr + instruction_size * 6, 8) && // Slli Rd, Rs, 8 + is_addi_at(instr + instruction_size * 7) && // addi + check_li64_data_dependency(instr); +} + +void NativeCall::verify() { + assert(NativeCall::is_call_at((address)this), "unexpected code at call site"); +} + +address NativeCall::destination() const { + address addr = (address)this; + assert(NativeInstruction::is_jal_at(instruction_address()), "inst must be jal."); + address destination = MacroAssembler::target_addr_for_insn(instruction_address()); + + // Do we use a trampoline stub for this call? + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); // Else we get assertion if nmethod is zombie. + assert(cb && cb->is_nmethod(), "sanity"); + nmethod *nm = (nmethod *)cb; + if (nm != NULL && nm->stub_contains(destination) && is_NativeCallTrampolineStub_at(destination)) { + // Yes we do, so get the destination from the trampoline stub. + const address trampoline_stub_addr = destination; + destination = nativeCallTrampolineStub_at(trampoline_stub_addr)->destination(); + } + + return destination; +} + +// Similar to replace_mt_safe, but just changes the destination. The +// important thing is that free-running threads are able to execute this +// call instruction at all times. +// +// Used in the runtime linkage of calls; see class CompiledIC. +// +// Add parameter assert_lock to switch off assertion +// during code generation, where no patching lock is needed. +void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { + assert(!assert_lock || + (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || + CompiledICLocker::is_safe(addr_at(0)), + "concurrent code patching"); + + ResourceMark rm; + address addr_call = addr_at(0); + assert(NativeCall::is_call_at(addr_call), "unexpected code at call site"); + + // Patch the constant in the call's trampoline stub. + address trampoline_stub_addr = get_trampoline(); + if (trampoline_stub_addr != NULL) { + assert (!is_NativeCallTrampolineStub_at(dest), "chained trampolines"); + nativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest); + } + + // Patch the call. + if (Assembler::reachable_from_branch_at(addr_call, dest)) { + set_destination(dest); + } else { + assert (trampoline_stub_addr != NULL, "we need a trampoline"); + set_destination(trampoline_stub_addr); + } + + ICache::invalidate_range(addr_call, instruction_size); +} + +address NativeCall::get_trampoline() { + address call_addr = addr_at(0); + + CodeBlob *code = CodeCache::find_blob(call_addr); + assert(code != NULL, "Could not find the containing code blob"); + + address jal_destination = MacroAssembler::pd_call_destination(call_addr); + if (code != NULL && code->contains(jal_destination) && is_NativeCallTrampolineStub_at(jal_destination)) { + return jal_destination; + } + + if (code != NULL && code->is_nmethod()) { + return trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + } + + return NULL; +} + +// Inserts a native call instruction at a given pc +void NativeCall::insert(address code_pos, address entry) { Unimplemented(); } + +//------------------------------------------------------------------- + +void NativeMovConstReg::verify() { + if (!(nativeInstruction_at(instruction_address())->is_movptr() || + is_auipc_at(instruction_address()))) { + fatal("should be MOVPTR or AUIPC"); + } +} + +intptr_t NativeMovConstReg::data() const { + address addr = MacroAssembler::target_addr_for_insn(instruction_address()); + if (maybe_cpool_ref(instruction_address())) { + return *(intptr_t*)addr; + } else { + return (intptr_t)addr; + } +} + +void NativeMovConstReg::set_data(intptr_t x) { + if (maybe_cpool_ref(instruction_address())) { + address addr = MacroAssembler::target_addr_for_insn(instruction_address()); + *(intptr_t*)addr = x; + } else { + // Store x into the instruction stream. + MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)x); + ICache::invalidate_range(instruction_address(), movptr_instruction_size); + } + + // Find and replace the oop/metadata corresponding to this + // instruction in oops section. + CodeBlob* cb = CodeCache::find_blob(instruction_address()); + nmethod* nm = cb->as_nmethod_or_null(); + if (nm != NULL) { + RelocIterator iter(nm, instruction_address(), next_instruction_address()); + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop* oop_addr = iter.oop_reloc()->oop_addr(); + *oop_addr = cast_to_oop(x); + break; + } else if (iter.type() == relocInfo::metadata_type) { + Metadata** metadata_addr = iter.metadata_reloc()->metadata_addr(); + *metadata_addr = (Metadata*)x; + break; + } + } + } +} + +void NativeMovConstReg::print() { + tty->print_cr(PTR_FORMAT ": mov reg, " INTPTR_FORMAT, + p2i(instruction_address()), data()); +} + +//------------------------------------------------------------------- + +int NativeMovRegMem::offset() const { + Unimplemented(); + return 0; +} + +void NativeMovRegMem::set_offset(int x) { Unimplemented(); } + +void NativeMovRegMem::verify() { + Unimplemented(); +} + +//-------------------------------------------------------------------------------- + +void NativeJump::verify() { } + + +void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) { +} + + +address NativeJump::jump_destination() const { + address dest = MacroAssembler::target_addr_for_insn(instruction_address()); + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about + // As a special case we also use sequence movptr_with_offset(r,0), jalr(r,0) + // i.e. jump to 0 when we need leave space for a wide immediate + // load + + // return -1 if jump to self or to 0 + if ((dest == (address) this) || dest == 0) { + dest = (address) -1; + } + + return dest; +}; + +void NativeJump::set_jump_destination(address dest) { + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about + if (dest == (address) -1) + dest = instruction_address(); + + MacroAssembler::pd_patch_instruction(instruction_address(), dest); + ICache::invalidate_range(instruction_address(), instruction_size); +} + +//------------------------------------------------------------------- + +address NativeGeneralJump::jump_destination() const { + NativeMovConstReg* move = nativeMovConstReg_at(instruction_address()); + address dest = (address) move->data(); + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about + // As a special case we also use jump to 0 when first generating + // a general jump + + // return -1 if jump to self or to 0 + if ((dest == (address) this) || dest == 0) { + dest = (address) -1; + } + + return dest; +} + +//------------------------------------------------------------------- + +bool NativeInstruction::is_safepoint_poll() { + return is_lwu_to_zr(address(this)); +} + +bool NativeInstruction::is_lwu_to_zr(address instr) { + assert_cond(instr != NULL); + return (extract_opcode(instr) == 0b0000011 && + extract_funct3(instr) == 0b110 && + extract_rd(instr) == zr); // zr +} + +// A 16-bit instruction with all bits ones is permanently reserved as an illegal instruction. +bool NativeInstruction::is_sigill_zombie_not_entrant() { + // jvmci + return uint_at(0) == 0xffffffff; +} + +void NativeIllegalInstruction::insert(address code_pos) { + assert_cond(code_pos != NULL); + *(juint*)code_pos = 0xffffffff; // all bits ones is permanently reserved as an illegal instruction +} + +bool NativeInstruction::is_stop() { + return uint_at(0) == 0xffffffff; // an illegal instruction +} + +//------------------------------------------------------------------- + +// MT-safe inserting of a jump over a jump or a nop (used by +// nmethod::make_not_entrant_or_zombie) + +void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { + + assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); + + assert(nativeInstruction_at(verified_entry)->is_jump_or_nop() || + nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(), + "riscv cannot replace non-jump with jump"); + + // Patch this nmethod atomically. + if (Assembler::reachable_from_branch_at(verified_entry, dest)) { + ptrdiff_t offset = dest - verified_entry; + guarantee(is_imm_in_range(offset, 20, 1), "offset is too large to be patched in one jal insrusction."); // 1M + + uint32_t insn = 0; + address pInsn = (address)&insn; + Assembler::patch(pInsn, 31, 31, (offset >> 20) & 0x1); + Assembler::patch(pInsn, 30, 21, (offset >> 1) & 0x3ff); + Assembler::patch(pInsn, 20, 20, (offset >> 11) & 0x1); + Assembler::patch(pInsn, 19, 12, (offset >> 12) & 0xff); + Assembler::patch(pInsn, 11, 7, 0); // zero, no link jump + Assembler::patch(pInsn, 6, 0, 0b1101111); // j, (jal x0 offset) + *(unsigned int*)verified_entry = insn; + } else { + // We use an illegal instruction for marking a method as + // not_entrant or zombie. + NativeIllegalInstruction::insert(verified_entry); + } + + ICache::invalidate_range(verified_entry, instruction_size); +} + +void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { + CodeBuffer cb(code_pos, instruction_size); + MacroAssembler a(&cb); + + int32_t offset = 0; + a.movptr_with_offset(t0, entry, offset); // lui, addi, slli, addi, slli + a.jalr(x0, t0, offset); // jalr + + ICache::invalidate_range(code_pos, instruction_size); +} + +// MT-safe patching of a long jump instruction. +void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) { + ShouldNotCallThis(); +} + + +address NativeCallTrampolineStub::destination(nmethod *nm) const { + return ptr_at(data_offset); +} + +void NativeCallTrampolineStub::set_destination(address new_destination) { + set_ptr_at(data_offset, new_destination); + OrderAccess::release(); +} + +uint32_t NativeMembar::get_kind() { + uint32_t insn = uint_at(0); + + uint32_t predecessor = Assembler::extract(insn, 27, 24); + uint32_t successor = Assembler::extract(insn, 23, 20); + + return MacroAssembler::pred_succ_to_membar_mask(predecessor, successor); +} + +void NativeMembar::set_kind(uint32_t order_kind) { + uint32_t predecessor = 0; + uint32_t successor = 0; + + MacroAssembler::membar_mask_to_pred_succ(order_kind, predecessor, successor); + + uint32_t insn = uint_at(0); + address pInsn = (address) &insn; + Assembler::patch(pInsn, 27, 24, predecessor); + Assembler::patch(pInsn, 23, 20, successor); + + address membar = addr_at(0); + *(unsigned int*) membar = insn; +} diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..718b2e3de6c5acc37ca3a9717062afbe392edd4a --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -0,0 +1,572 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_NATIVEINST_RISCV_HPP +#define CPU_RISCV_NATIVEINST_RISCV_HPP + +#include "asm/assembler.hpp" +#include "runtime/icache.hpp" +#include "runtime/os.hpp" + +// We have interfaces for the following instructions: +// - NativeInstruction +// - - NativeCall +// - - NativeMovConstReg +// - - NativeMovRegMem +// - - NativeJump +// - - NativeGeneralJump +// - - NativeIllegalInstruction +// - - NativeCallTrampolineStub +// - - NativeMembar +// - - NativeFenceI + +// The base class for different kinds of native instruction abstractions. +// Provides the primitive operations to manipulate code relative to this. + +class NativeCall; + +class NativeInstruction { + friend class Relocation; + friend bool is_NativeCallTrampolineStub_at(address); + public: + enum { + instruction_size = 4, + compressed_instruction_size = 2, + }; + + juint encoding() const { + return uint_at(0); + } + + bool is_jal() const { return is_jal_at(addr_at(0)); } + bool is_movptr() const { return is_movptr_at(addr_at(0)); } + bool is_call() const { return is_call_at(addr_at(0)); } + bool is_jump() const { return is_jump_at(addr_at(0)); } + + static bool is_jal_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b1101111; } + static bool is_jalr_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b1100111 && extract_funct3(instr) == 0b000; } + static bool is_branch_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b1100011; } + static bool is_ld_at(address instr) { assert_cond(instr != NULL); return is_load_at(instr) && extract_funct3(instr) == 0b011; } + static bool is_load_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0000011; } + static bool is_float_load_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0000111; } + static bool is_auipc_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0010111; } + static bool is_jump_at(address instr) { assert_cond(instr != NULL); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } + static bool is_addi_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } + static bool is_addiw_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } + static bool is_lui_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0110111; } + static bool is_slli_shift_at(address instr, uint32_t shift) { + assert_cond(instr != NULL); + return (extract_opcode(instr) == 0b0010011 && // opcode field + extract_funct3(instr) == 0b001 && // funct3 field, select the type of operation + Assembler::extract(((unsigned*)instr)[0], 25, 20) == shift); // shamt field + } + + static Register extract_rs1(address instr); + static Register extract_rs2(address instr); + static Register extract_rd(address instr); + static uint32_t extract_opcode(address instr); + static uint32_t extract_funct3(address instr); + + // the instruction sequence of movptr is as below: + // lui + // addi + // slli + // addi + // slli + // addi/jalr/load + static bool check_movptr_data_dependency(address instr) { + address lui = instr; + address addi1 = lui + instruction_size; + address slli1 = addi1 + instruction_size; + address addi2 = slli1 + instruction_size; + address slli2 = addi2 + instruction_size; + address last_instr = slli2 + instruction_size; + return extract_rs1(addi1) == extract_rd(lui) && + extract_rs1(addi1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(slli2) && + extract_rs1(last_instr) == extract_rd(slli2); + } + + // the instruction sequence of li64 is as below: + // lui + // addi + // slli + // addi + // slli + // addi + // slli + // addi + static bool check_li64_data_dependency(address instr) { + address lui = instr; + address addi1 = lui + instruction_size; + address slli1 = addi1 + instruction_size; + address addi2 = slli1 + instruction_size; + address slli2 = addi2 + instruction_size; + address addi3 = slli2 + instruction_size; + address slli3 = addi3 + instruction_size; + address addi4 = slli3 + instruction_size; + return extract_rs1(addi1) == extract_rd(lui) && + extract_rs1(addi1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(slli2) && + extract_rs1(addi3) == extract_rd(slli2) && + extract_rs1(addi3) == extract_rd(addi3) && + extract_rs1(slli3) == extract_rd(addi3) && + extract_rs1(slli3) == extract_rd(slli3) && + extract_rs1(addi4) == extract_rd(slli3) && + extract_rs1(addi4) == extract_rd(addi4); + } + + // the instruction sequence of li32 is as below: + // lui + // addiw + static bool check_li32_data_dependency(address instr) { + address lui = instr; + address addiw = lui + instruction_size; + + return extract_rs1(addiw) == extract_rd(lui) && + extract_rs1(addiw) == extract_rd(addiw); + } + + // the instruction sequence of pc-relative is as below: + // auipc + // jalr/addi/load/float_load + static bool check_pc_relative_data_dependency(address instr) { + address auipc = instr; + address last_instr = auipc + instruction_size; + + return extract_rs1(last_instr) == extract_rd(auipc); + } + + // the instruction sequence of load_label is as below: + // auipc + // load + static bool check_load_pc_relative_data_dependency(address instr) { + address auipc = instr; + address load = auipc + instruction_size; + + return extract_rd(load) == extract_rd(auipc) && + extract_rs1(load) == extract_rd(load); + } + + static bool is_movptr_at(address instr); + static bool is_li32_at(address instr); + static bool is_li64_at(address instr); + static bool is_pc_relative_at(address branch); + static bool is_load_pc_relative_at(address branch); + + static bool is_call_at(address instr) { + if (is_jal_at(instr) || is_jalr_at(instr)) { + return true; + } + return false; + } + static bool is_lwu_to_zr(address instr); + + inline bool is_nop(); + inline bool is_jump_or_nop(); + bool is_safepoint_poll(); + bool is_sigill_zombie_not_entrant(); + bool is_stop(); + + protected: + address addr_at(int offset) const { return address(this) + offset; } + + jint int_at(int offset) const { return *(jint*) addr_at(offset); } + juint uint_at(int offset) const { return *(juint*) addr_at(offset); } + + address ptr_at(int offset) const { return *(address*) addr_at(offset); } + + oop oop_at (int offset) const { return *(oop*) addr_at(offset); } + + + void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; } + void set_uint_at(int offset, jint i) { *(juint*)addr_at(offset) = i; } + void set_ptr_at (int offset, address ptr) { *(address*) addr_at(offset) = ptr; } + void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; } + + public: + + inline friend NativeInstruction* nativeInstruction_at(address addr); + + static bool maybe_cpool_ref(address instr) { + return is_auipc_at(instr); + } + + bool is_membar() { + return (uint_at(0) & 0x7f) == 0b1111 && extract_funct3(addr_at(0)) == 0; + } +}; + +inline NativeInstruction* nativeInstruction_at(address addr) { + return (NativeInstruction*)addr; +} + +// The natural type of an RISCV instruction is uint32_t +inline NativeInstruction* nativeInstruction_at(uint32_t *addr) { + return (NativeInstruction*)addr; +} + +inline NativeCall* nativeCall_at(address addr); +// The NativeCall is an abstraction for accessing/manipulating native +// call instructions (used to manipulate inline caches, primitive & +// DSO calls, etc.). + +class NativeCall: public NativeInstruction { + public: + enum RISCV_specific_constants { + instruction_size = 4, + instruction_offset = 0, + displacement_offset = 0, + return_address_offset = 4 + }; + + address instruction_address() const { return addr_at(instruction_offset); } + address next_instruction_address() const { return addr_at(return_address_offset); } + address return_address() const { return addr_at(return_address_offset); } + address destination() const; + + void set_destination(address dest) { + assert(is_jal(), "Should be jal instruction!"); + intptr_t offset = (intptr_t)(dest - instruction_address()); + assert((offset & 0x1) == 0, "bad alignment"); + assert(is_imm_in_range(offset, 20, 1), "encoding constraint"); + unsigned int insn = 0b1101111; // jal + address pInsn = (address)(&insn); + Assembler::patch(pInsn, 31, 31, (offset >> 20) & 0x1); + Assembler::patch(pInsn, 30, 21, (offset >> 1) & 0x3ff); + Assembler::patch(pInsn, 20, 20, (offset >> 11) & 0x1); + Assembler::patch(pInsn, 19, 12, (offset >> 12) & 0xff); + Assembler::patch(pInsn, 11, 7, ra->encoding()); // Rd must be x1, need ra + set_int_at(displacement_offset, insn); + } + + void verify_alignment() {} // do nothing on riscv + void verify(); + void print(); + + // Creation + inline friend NativeCall* nativeCall_at(address addr); + inline friend NativeCall* nativeCall_before(address return_address); + + static bool is_call_before(address return_address) { + return is_call_at(return_address - NativeCall::return_address_offset); + } + + // MT-safe patching of a call instruction. + static void insert(address code_pos, address entry); + + static void replace_mt_safe(address instr_addr, address code_buffer); + + // Similar to replace_mt_safe, but just changes the destination. The + // important thing is that free-running threads are able to execute + // this call instruction at all times. If the call is an immediate BL + // instruction we can simply rely on atomicity of 32-bit writes to + // make sure other threads will see no intermediate states. + + // We cannot rely on locks here, since the free-running threads must run at + // full speed. + // + // Used in the runtime linkage of calls; see class CompiledIC. + // (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.) + + // The parameter assert_lock disables the assertion during code generation. + void set_destination_mt_safe(address dest, bool assert_lock = true); + + address get_trampoline(); +}; + +inline NativeCall* nativeCall_at(address addr) { + assert_cond(addr != NULL); + NativeCall* call = (NativeCall*)(addr - NativeCall::instruction_offset); +#ifdef ASSERT + call->verify(); +#endif + return call; +} + +inline NativeCall* nativeCall_before(address return_address) { + assert_cond(return_address != NULL); + NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset); +#ifdef ASSERT + call->verify(); +#endif + return call; +} + +// An interface for accessing/manipulating native mov reg, imm instructions. +// (used to manipulate inlined 64-bit data calls, etc.) +class NativeMovConstReg: public NativeInstruction { + public: + enum RISCV_specific_constants { + movptr_instruction_size = 6 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli, addi. See movptr(). + movptr_with_offset_instruction_size = 5 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli. See movptr_with_offset(). + load_pc_relative_instruction_size = 2 * NativeInstruction::instruction_size, // auipc, ld + instruction_offset = 0, + displacement_offset = 0 + }; + + address instruction_address() const { return addr_at(instruction_offset); } + address next_instruction_address() const { + // if the instruction at 5 * instruction_size is addi, + // it means a lui + addi + slli + addi + slli + addi instruction sequence, + // and the next instruction address should be addr_at(6 * instruction_size). + // However, when the instruction at 5 * instruction_size isn't addi, + // the next instruction address should be addr_at(5 * instruction_size) + if (nativeInstruction_at(instruction_address())->is_movptr()) { + if (is_addi_at(addr_at(movptr_with_offset_instruction_size))) { + // Assume: lui, addi, slli, addi, slli, addi + return addr_at(movptr_instruction_size); + } else { + // Assume: lui, addi, slli, addi, slli + return addr_at(movptr_with_offset_instruction_size); + } + } else if (is_load_pc_relative_at(instruction_address())) { + // Assume: auipc, ld + return addr_at(load_pc_relative_instruction_size); + } + guarantee(false, "Unknown instruction in NativeMovConstReg"); + return NULL; + } + + intptr_t data() const; + void set_data(intptr_t x); + + void flush() { + if (!maybe_cpool_ref(instruction_address())) { + ICache::invalidate_range(instruction_address(), movptr_instruction_size); + } + } + + void verify(); + void print(); + + // Creation + inline friend NativeMovConstReg* nativeMovConstReg_at(address addr); + inline friend NativeMovConstReg* nativeMovConstReg_before(address addr); +}; + +inline NativeMovConstReg* nativeMovConstReg_at(address addr) { + assert_cond(addr != NULL); + NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_offset); +#ifdef ASSERT + test->verify(); +#endif + return test; +} + +inline NativeMovConstReg* nativeMovConstReg_before(address addr) { + assert_cond(addr != NULL); + NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset); +#ifdef ASSERT + test->verify(); +#endif + return test; +} + +// RISCV should not use C1 runtime patching, so just leave NativeMovRegMem Unimplemented. +class NativeMovRegMem: public NativeInstruction { + public: + int instruction_start() const { + Unimplemented(); + return 0; + } + + address instruction_address() const { + Unimplemented(); + return NULL; + } + + int num_bytes_to_end_of_patch() const { + Unimplemented(); + return 0; + } + + int offset() const; + + void set_offset(int x); + + void add_offset_in_bytes(int add_offset) { Unimplemented(); } + + void verify(); + void print(); + + private: + inline friend NativeMovRegMem* nativeMovRegMem_at (address addr); +}; + +inline NativeMovRegMem* nativeMovRegMem_at (address addr) { + Unimplemented(); + return NULL; +} + +class NativeJump: public NativeInstruction { + public: + enum RISCV_specific_constants { + instruction_size = NativeInstruction::instruction_size, + instruction_offset = 0, + data_offset = 0, + next_instruction_offset = NativeInstruction::instruction_size + }; + + address instruction_address() const { return addr_at(instruction_offset); } + address next_instruction_address() const { return addr_at(instruction_size); } + address jump_destination() const; + void set_jump_destination(address dest); + + // Creation + inline friend NativeJump* nativeJump_at(address address); + + void verify(); + + // Insertion of native jump instruction + static void insert(address code_pos, address entry); + // MT-safe insertion of native jump at verified method entry + static void check_verified_entry_alignment(address entry, address verified_entry); + static void patch_verified_entry(address entry, address verified_entry, address dest); +}; + +inline NativeJump* nativeJump_at(address addr) { + NativeJump* jump = (NativeJump*)(addr - NativeJump::instruction_offset); +#ifdef ASSERT + jump->verify(); +#endif + return jump; +} + +class NativeGeneralJump: public NativeJump { +public: + enum RISCV_specific_constants { + instruction_size = 6 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli, jalr + instruction_offset = 0, + data_offset = 0, + next_instruction_offset = 6 * NativeInstruction::instruction_size // lui, addi, slli, addi, slli, jalr + }; + + address jump_destination() const; + + static void insert_unconditional(address code_pos, address entry); + static void replace_mt_safe(address instr_addr, address code_buffer); +}; + +inline NativeGeneralJump* nativeGeneralJump_at(address addr) { + assert_cond(addr != NULL); + NativeGeneralJump* jump = (NativeGeneralJump*)(addr); + debug_only(jump->verify();) + return jump; +} + +class NativeIllegalInstruction: public NativeInstruction { + public: + // Insert illegal opcode as specific address + static void insert(address code_pos); +}; + +inline bool NativeInstruction::is_nop() { + uint32_t insn = *(uint32_t*)addr_at(0); + return insn == 0x13; +} + +inline bool NativeInstruction::is_jump_or_nop() { + return is_nop() || is_jump(); +} + +// Call trampoline stubs. +class NativeCallTrampolineStub : public NativeInstruction { + public: + + enum RISCV_specific_constants { + // Refer to function emit_trampoline_stub. + instruction_size = 3 * NativeInstruction::instruction_size + wordSize, // auipc + ld + jr + target address + data_offset = 3 * NativeInstruction::instruction_size, // auipc + ld + jr + }; + + address destination(nmethod *nm = NULL) const; + void set_destination(address new_destination); + ptrdiff_t destination_offset() const; +}; + +inline bool is_NativeCallTrampolineStub_at(address addr) { + // Ensure that the stub is exactly + // ld t0, L--->auipc + ld + // jr t0 + // L: + + // judge inst + register + imm + // 1). check the instructions: auipc + ld + jalr + // 2). check if auipc[11:7] == t0 and ld[11:7] == t0 and ld[19:15] == t0 && jr[19:15] == t0 + // 3). check if the offset in ld[31:20] equals the data_offset + assert_cond(addr != NULL); + const int instr_size = NativeInstruction::instruction_size; + if (NativeInstruction::is_auipc_at(addr) && + NativeInstruction::is_ld_at(addr + instr_size) && + NativeInstruction::is_jalr_at(addr + 2 * instr_size) && + (NativeInstruction::extract_rd(addr) == x5) && + (NativeInstruction::extract_rd(addr + instr_size) == x5) && + (NativeInstruction::extract_rs1(addr + instr_size) == x5) && + (NativeInstruction::extract_rs1(addr + 2 * instr_size) == x5) && + (Assembler::extract(((unsigned*)addr)[1], 31, 20) == NativeCallTrampolineStub::data_offset)) { + return true; + } + return false; +} + +inline NativeCallTrampolineStub* nativeCallTrampolineStub_at(address addr) { + assert_cond(addr != NULL); + assert(is_NativeCallTrampolineStub_at(addr), "no call trampoline found"); + return (NativeCallTrampolineStub*)addr; +} + +class NativeMembar : public NativeInstruction { +public: + uint32_t get_kind(); + void set_kind(uint32_t order_kind); +}; + +inline NativeMembar *NativeMembar_at(address addr) { + assert_cond(addr != NULL); + assert(nativeInstruction_at(addr)->is_membar(), "no membar found"); + return (NativeMembar*)addr; +} + +class NativeFenceI : public NativeInstruction { +public: + static inline int instruction_size() { + // 2 for fence.i + fence + return (UseConservativeFence ? 2 : 1) * NativeInstruction::instruction_size; + } +}; + +#endif // CPU_RISCV_NATIVEINST_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.cpp b/src/hotspot/cpu/riscv/registerMap_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26c1edc36ffc4c0ef65d1eb380b3b151b8026d2a --- /dev/null +++ b/src/hotspot/cpu/riscv/registerMap_riscv.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/registerMap.hpp" +#include "vmreg_riscv.inline.hpp" + +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + if (base_reg->is_VectorRegister()) { + assert(base_reg->is_concrete(), "must pass base reg"); + int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_fpr) / + VectorRegisterImpl::max_slots_per_register; + intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; + address base_location = location(base_reg); + if (base_location != NULL) { + return base_location + offset_in_bytes; + } else { + return NULL; + } + } else { + return location(base_reg->next(slot_idx)); + } +} diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.hpp b/src/hotspot/cpu/riscv/registerMap_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f34349811a9ca2cb2e27bd7afb52c83157cb2cb0 --- /dev/null +++ b/src/hotspot/cpu/riscv/registerMap_riscv.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_REGISTERMAP_RISCV_HPP +#define CPU_RISCV_REGISTERMAP_RISCV_HPP + +// machine-dependent implemention for register maps + friend class frame; + + private: + // This is the hook for finding a register in an "well-known" location, + // such as a register block of a predetermined format. + address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg base_reg, int slot_idx) const; + + // no PD state to clear or copy: + void pd_clear() {} + void pd_initialize() {} + void pd_initialize_from(const RegisterMap* map) {} + +#endif // CPU_RISCV_REGISTERMAP_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/register_riscv.cpp b/src/hotspot/cpu/riscv/register_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8116e9df8c7fa82c9213cf9c8bf591a110afddc --- /dev/null +++ b/src/hotspot/cpu/riscv/register_riscv.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "register_riscv.hpp" + +REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_registers); +REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); +REGISTER_IMPL_DEFINITION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); + +const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * + RegisterImpl::max_slots_per_register; + +const int ConcreteRegisterImpl::max_fpr = + ConcreteRegisterImpl::max_gpr + + FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register; + +const int ConcreteRegisterImpl::max_vpr = + ConcreteRegisterImpl::max_fpr + + VectorRegisterImpl::number_of_registers * VectorRegisterImpl::max_slots_per_register; + + +const char* RegisterImpl::name() const { + static const char *const names[number_of_registers] = { + "zr", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "x9", + "c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7", + "x18", "x19", "esp", "xdispatch", "xbcp", "xthread", "xlocals", + "xmonitors", "xcpool", "xheapbase", "x28", "x29", "x30", "xmethod" + }; + return is_valid() ? names[encoding()] : "noreg"; +} + +const char* FloatRegisterImpl::name() const { + static const char *const names[number_of_registers] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" + }; + return is_valid() ? names[encoding()] : "noreg"; +} + +const char* VectorRegisterImpl::name() const { + static const char *const names[number_of_registers] = { + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" + }; + return is_valid() ? names[encoding()] : "noreg"; +} diff --git a/src/hotspot/cpu/riscv/register_riscv.hpp b/src/hotspot/cpu/riscv/register_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a9200cac647b40c3d7d8eb9d5fdb77bae738f352 --- /dev/null +++ b/src/hotspot/cpu/riscv/register_riscv.hpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_REGISTER_RISCV_HPP +#define CPU_RISCV_REGISTER_RISCV_HPP + +#include "asm/register.hpp" + +#define CSR_FFLAGS 0x001 // Floating-Point Accrued Exceptions. +#define CSR_FRM 0x002 // Floating-Point Dynamic Rounding Mode. +#define CSR_FCSR 0x003 // Floating-Point Control and Status Register (frm + fflags). +#define CSR_VSTART 0x008 // Vector start position +#define CSR_VXSAT 0x009 // Fixed-Point Saturate Flag +#define CSR_VXRM 0x00A // Fixed-Point Rounding Mode +#define CSR_VCSR 0x00F // Vector control and status register +#define CSR_VL 0xC20 // Vector length +#define CSR_VTYPE 0xC21 // Vector data type register +#define CSR_VLENB 0xC22 // VLEN/8 (vector register length in bytes) +#define CSR_CYCLE 0xc00 // Cycle counter for RDCYCLE instruction. +#define CSR_TIME 0xc01 // Timer for RDTIME instruction. +#define CSR_INSTERT 0xc02 // Instructions-retired counter for RDINSTRET instruction. + +class VMRegImpl; +typedef VMRegImpl* VMReg; + +// Use Register as shortcut +class RegisterImpl; +typedef const RegisterImpl* Register; + +inline constexpr Register as_Register(int encoding); + +class RegisterImpl: public AbstractRegisterImpl { + static constexpr Register first(); + + public: + enum { + number_of_registers = 32, + max_slots_per_register = 2, + + // integer registers x8 - x15 and floating-point registers f8 - f15 are allocatable + // for compressed instructions. See Table 17.2 in spec. + compressed_register_base = 8, + compressed_register_top = 15, + }; + + // derived registers, offsets, and addresses + const Register successor() const { return this + 1; } + + // construction + inline friend constexpr Register as_Register(int encoding); + + VMReg as_VMReg() const; + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + int encoding_nocheck() const { return this - first(); } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + + // for rvc + int compressed_encoding() const { + assert(is_compressed_valid(), "invalid compressed register"); + return encoding() - compressed_register_base; + } + + int compressed_encoding_nocheck() const { + return encoding_nocheck() - compressed_register_base; + } + + bool is_compressed_valid() const { + return encoding_nocheck() >= compressed_register_base && + encoding_nocheck() <= compressed_register_top; + } +}; + +REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_registers); + +// The integer registers of the RISCV architecture + +CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1)); + +CONSTANT_REGISTER_DECLARATION(Register, x0, (0)); +CONSTANT_REGISTER_DECLARATION(Register, x1, (1)); +CONSTANT_REGISTER_DECLARATION(Register, x2, (2)); +CONSTANT_REGISTER_DECLARATION(Register, x3, (3)); +CONSTANT_REGISTER_DECLARATION(Register, x4, (4)); +CONSTANT_REGISTER_DECLARATION(Register, x5, (5)); +CONSTANT_REGISTER_DECLARATION(Register, x6, (6)); +CONSTANT_REGISTER_DECLARATION(Register, x7, (7)); +CONSTANT_REGISTER_DECLARATION(Register, x8, (8)); +CONSTANT_REGISTER_DECLARATION(Register, x9, (9)); +CONSTANT_REGISTER_DECLARATION(Register, x10, (10)); +CONSTANT_REGISTER_DECLARATION(Register, x11, (11)); +CONSTANT_REGISTER_DECLARATION(Register, x12, (12)); +CONSTANT_REGISTER_DECLARATION(Register, x13, (13)); +CONSTANT_REGISTER_DECLARATION(Register, x14, (14)); +CONSTANT_REGISTER_DECLARATION(Register, x15, (15)); +CONSTANT_REGISTER_DECLARATION(Register, x16, (16)); +CONSTANT_REGISTER_DECLARATION(Register, x17, (17)); +CONSTANT_REGISTER_DECLARATION(Register, x18, (18)); +CONSTANT_REGISTER_DECLARATION(Register, x19, (19)); +CONSTANT_REGISTER_DECLARATION(Register, x20, (20)); +CONSTANT_REGISTER_DECLARATION(Register, x21, (21)); +CONSTANT_REGISTER_DECLARATION(Register, x22, (22)); +CONSTANT_REGISTER_DECLARATION(Register, x23, (23)); +CONSTANT_REGISTER_DECLARATION(Register, x24, (24)); +CONSTANT_REGISTER_DECLARATION(Register, x25, (25)); +CONSTANT_REGISTER_DECLARATION(Register, x26, (26)); +CONSTANT_REGISTER_DECLARATION(Register, x27, (27)); +CONSTANT_REGISTER_DECLARATION(Register, x28, (28)); +CONSTANT_REGISTER_DECLARATION(Register, x29, (29)); +CONSTANT_REGISTER_DECLARATION(Register, x30, (30)); +CONSTANT_REGISTER_DECLARATION(Register, x31, (31)); + +// Use FloatRegister as shortcut +class FloatRegisterImpl; +typedef const FloatRegisterImpl* FloatRegister; + +inline constexpr FloatRegister as_FloatRegister(int encoding); + +// The implementation of floating point registers for the architecture +class FloatRegisterImpl: public AbstractRegisterImpl { + static constexpr FloatRegister first(); + + public: + enum { + number_of_registers = 32, + max_slots_per_register = 2, + + // float registers in the range of [f8~f15] correspond to RVC. Please see Table 16.2 in spec. + compressed_register_base = 8, + compressed_register_top = 15, + }; + + // construction + inline friend constexpr FloatRegister as_FloatRegister(int encoding); + + VMReg as_VMReg() const; + + // derived registers, offsets, and addresses + FloatRegister successor() const { + return as_FloatRegister((encoding() + 1) % (unsigned)number_of_registers); + } + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + int encoding_nocheck() const { return this - first(); } + int is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + + // for rvc + int compressed_encoding() const { + assert(is_compressed_valid(), "invalid compressed register"); + return encoding() - compressed_register_base; + } + + int compressed_encoding_nocheck() const { + return encoding_nocheck() - compressed_register_base; + } + + bool is_compressed_valid() const { + return encoding_nocheck() >= compressed_register_base && + encoding_nocheck() <= compressed_register_top; + } +}; + +REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); + +// The float registers of the RISCV architecture + +CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1)); + +CONSTANT_REGISTER_DECLARATION(FloatRegister, f0 , ( 0)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f1 , ( 1)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f2 , ( 2)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f3 , ( 3)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f4 , ( 4)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f5 , ( 5)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f6 , ( 6)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f7 , ( 7)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f8 , ( 8)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f9 , ( 9)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f10 , (10)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f11 , (11)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f12 , (12)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f13 , (13)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f14 , (14)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f15 , (15)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f16 , (16)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f17 , (17)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f18 , (18)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f19 , (19)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f20 , (20)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f21 , (21)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f22 , (22)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f23 , (23)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f24 , (24)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f25 , (25)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f26 , (26)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f27 , (27)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f28 , (28)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f29 , (29)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f30 , (30)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, f31 , (31)); + +// Use VectorRegister as shortcut +class VectorRegisterImpl; +typedef const VectorRegisterImpl* VectorRegister; + +inline constexpr VectorRegister as_VectorRegister(int encoding); + +// The implementation of vector registers for RVV +class VectorRegisterImpl: public AbstractRegisterImpl { + static constexpr VectorRegister first(); + + public: + enum { + number_of_registers = 32, + max_slots_per_register = 4 + }; + + // construction + inline friend constexpr VectorRegister as_VectorRegister(int encoding); + + VMReg as_VMReg() const; + + // derived registers, offsets, and addresses + VectorRegister successor() const { return this + 1; } + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + int encoding_nocheck() const { return this - first(); } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + +}; + +REGISTER_IMPL_DECLARATION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); + +// The vector registers of RVV +CONSTANT_REGISTER_DECLARATION(VectorRegister, vnoreg , (-1)); + +CONSTANT_REGISTER_DECLARATION(VectorRegister, v0 , ( 0)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v1 , ( 1)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v2 , ( 2)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v3 , ( 3)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v4 , ( 4)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v5 , ( 5)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v6 , ( 6)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v7 , ( 7)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v8 , ( 8)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v9 , ( 9)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v10 , (10)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v11 , (11)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v12 , (12)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v13 , (13)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v14 , (14)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v15 , (15)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v16 , (16)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v17 , (17)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v18 , (18)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v19 , (19)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v20 , (20)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v21 , (21)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v22 , (22)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v23 , (23)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v24 , (24)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v25 , (25)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v26 , (26)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v27 , (27)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v28 , (28)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v29 , (29)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v30 , (30)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, v31 , (31)); + + +// Need to know the total number of registers of all sorts for SharedInfo. +// Define a class that exports it. +class ConcreteRegisterImpl : public AbstractRegisterImpl { + public: + enum { + // A big enough number for C2: all the registers plus flags + // This number must be large enough to cover REG_COUNT (defined by c2) registers. + // There is no requirement that any ordering here matches any ordering c2 gives + // it's optoregs. + + number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers + + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + + VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers) + }; + + // added to make it compile + static const int max_gpr; + static const int max_fpr; + static const int max_vpr; +}; + +typedef AbstractRegSet RegSet; +typedef AbstractRegSet FloatRegSet; +typedef AbstractRegSet VectorRegSet; + +#endif // CPU_RISCV_REGISTER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..228a64eae2c6491ff3c03f01da14de82de22d89c --- /dev/null +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "code/relocInfo.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/safepoint.hpp" + +void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { + if (verify_only) { + return; + } + + int bytes; + + switch (type()) { + case relocInfo::oop_type: { + oop_Relocation *reloc = (oop_Relocation *)this; + // in movoop when BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate + if (NativeInstruction::is_load_pc_relative_at(addr())) { + address constptr = (address)code()->oop_addr_at(reloc->oop_index()); + bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); + assert(*(address*)constptr == x, "error in oop relocation"); + } else { + bytes = MacroAssembler::patch_oop(addr(), x); + } + break; + } + default: + bytes = MacroAssembler::pd_patch_instruction_size(addr(), x); + break; + } + ICache::invalidate_range(addr(), bytes); +} + +address Relocation::pd_call_destination(address orig_addr) { + assert(is_call(), "should be an address instruction here"); + if (NativeCall::is_call_at(addr())) { + address trampoline = nativeCall_at(addr())->get_trampoline(); + if (trampoline != NULL) { + return nativeCallTrampolineStub_at(trampoline)->destination(); + } + } + if (orig_addr != NULL) { + // the extracted address from the instructions in address orig_addr + address new_addr = MacroAssembler::pd_call_destination(orig_addr); + // If call is branch to self, don't try to relocate it, just leave it + // as branch to self. This happens during code generation if the code + // buffer expands. It will be relocated to the trampoline above once + // code generation is complete. + new_addr = (new_addr == orig_addr) ? addr() : new_addr; + return new_addr; + } + return MacroAssembler::pd_call_destination(addr()); +} + +void Relocation::pd_set_call_destination(address x) { + assert(is_call(), "should be an address instruction here"); + if (NativeCall::is_call_at(addr())) { + address trampoline = nativeCall_at(addr())->get_trampoline(); + if (trampoline != NULL) { + nativeCall_at(addr())->set_destination_mt_safe(x, /* assert_lock */false); + return; + } + } + MacroAssembler::pd_patch_instruction_size(addr(), x); + address pd_call = pd_call_destination(addr()); + assert(pd_call == x, "fail in reloc"); +} + +address* Relocation::pd_address_in_code() { + assert(NativeCall::is_load_pc_relative_at(addr()), "Not the expected instruction sequence!"); + return (address*)(MacroAssembler::target_addr_for_insn(addr())); +} + +address Relocation::pd_get_address_from_code() { + return MacroAssembler::pd_call_destination(addr()); +} + +void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { + if (NativeInstruction::maybe_cpool_ref(addr())) { + address old_addr = old_addr_for(addr(), src, dest); + MacroAssembler::pd_patch_instruction_size(addr(), MacroAssembler::target_addr_for_insn(old_addr)); + } +} + +void metadata_Relocation::pd_fix_value(address x) { +} diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.hpp b/src/hotspot/cpu/riscv/relocInfo_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..840ed935d88b74c2462b5f96f8bbbd6d9cdd9d6b --- /dev/null +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_RELOCINFO_RISCV_HPP +#define CPU_RISCV_RELOCINFO_RISCV_HPP + + // machine-dependent parts of class relocInfo + private: + enum { + // Relocations are byte-aligned. + offset_unit = 1, + // Must be at least 1 for RelocInfo::narrow_oop_in_const. + format_width = 1 + }; + + public: + + // This platform has no oops in the code that are not also + // listed in the oop section. + static bool mustIterateImmediateOopsInCode() { return false; } + +#endif // CPU_RISCV_RELOCINFO_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad new file mode 100644 index 0000000000000000000000000000000000000000..d06991b0854fc202bba0391ca185db976a024080 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -0,0 +1,10611 @@ +// +// Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. +// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +// RISCV Architecture Description File + +//----------REGISTER DEFINITION BLOCK------------------------------------------ +// This information is used by the matcher and the register allocator to +// describe individual registers and classes of registers within the target +// archtecture. + +register %{ +//----------Architecture Description Register Definitions---------------------- +// General Registers +// "reg_def" name ( register save type, C convention save type, +// ideal register type, encoding ); +// Register Save Types: +// +// NS = No-Save: The register allocator assumes that these registers +// can be used without saving upon entry to the method, & +// that they do not need to be saved at call sites. +// +// SOC = Save-On-Call: The register allocator assumes that these registers +// can be used without saving upon entry to the method, +// but that they must be saved at call sites. +// +// SOE = Save-On-Entry: The register allocator assumes that these registers +// must be saved before using them upon entry to the +// method, but they do not need to be saved at call +// sites. +// +// AS = Always-Save: The register allocator assumes that these registers +// must be saved before using them upon entry to the +// method, & that they must be saved at call sites. +// +// Ideal Register Type is used to determine how to save & restore a +// register. Op_RegI will get spilled with LoadI/StoreI, Op_RegP will get +// spilled with LoadP/StoreP. If the register supports both, use Op_RegI. +// +// The encoding number is the actual bit-pattern placed into the opcodes. + +// We must define the 64 bit int registers in two 32 bit halves, the +// real lower register and a virtual upper half register. upper halves +// are used by the register allocator but are not actually supplied as +// operands to memory ops. +// +// follow the C1 compiler in making registers +// +// x7, x9-x17, x27-x31 volatile (caller save) +// x0-x4, x8, x23 system (no save, no allocate) +// x5-x6 non-allocatable (so we can use them as temporary regs) + +// +// as regards Java usage. we don't use any callee save registers +// because this makes it difficult to de-optimise a frame (see comment +// in x86 implementation of Deoptimization::unwind_callee_save_values) +// + +// General Registers + +reg_def R0 ( NS, NS, Op_RegI, 0, x0->as_VMReg() ); // zr +reg_def R0_H ( NS, NS, Op_RegI, 0, x0->as_VMReg()->next() ); +reg_def R1 ( NS, SOC, Op_RegI, 1, x1->as_VMReg() ); // ra +reg_def R1_H ( NS, SOC, Op_RegI, 1, x1->as_VMReg()->next() ); +reg_def R2 ( NS, SOE, Op_RegI, 2, x2->as_VMReg() ); // sp +reg_def R2_H ( NS, SOE, Op_RegI, 2, x2->as_VMReg()->next() ); +reg_def R3 ( NS, NS, Op_RegI, 3, x3->as_VMReg() ); // gp +reg_def R3_H ( NS, NS, Op_RegI, 3, x3->as_VMReg()->next() ); +reg_def R4 ( NS, NS, Op_RegI, 4, x4->as_VMReg() ); // tp +reg_def R4_H ( NS, NS, Op_RegI, 4, x4->as_VMReg()->next() ); +reg_def R7 ( SOC, SOC, Op_RegI, 7, x7->as_VMReg() ); +reg_def R7_H ( SOC, SOC, Op_RegI, 7, x7->as_VMReg()->next() ); +reg_def R8 ( NS, SOE, Op_RegI, 8, x8->as_VMReg() ); // fp +reg_def R8_H ( NS, SOE, Op_RegI, 8, x8->as_VMReg()->next() ); +reg_def R9 ( SOC, SOE, Op_RegI, 9, x9->as_VMReg() ); +reg_def R9_H ( SOC, SOE, Op_RegI, 9, x9->as_VMReg()->next() ); +reg_def R10 ( SOC, SOC, Op_RegI, 10, x10->as_VMReg() ); +reg_def R10_H ( SOC, SOC, Op_RegI, 10, x10->as_VMReg()->next()); +reg_def R11 ( SOC, SOC, Op_RegI, 11, x11->as_VMReg() ); +reg_def R11_H ( SOC, SOC, Op_RegI, 11, x11->as_VMReg()->next()); +reg_def R12 ( SOC, SOC, Op_RegI, 12, x12->as_VMReg() ); +reg_def R12_H ( SOC, SOC, Op_RegI, 12, x12->as_VMReg()->next()); +reg_def R13 ( SOC, SOC, Op_RegI, 13, x13->as_VMReg() ); +reg_def R13_H ( SOC, SOC, Op_RegI, 13, x13->as_VMReg()->next()); +reg_def R14 ( SOC, SOC, Op_RegI, 14, x14->as_VMReg() ); +reg_def R14_H ( SOC, SOC, Op_RegI, 14, x14->as_VMReg()->next()); +reg_def R15 ( SOC, SOC, Op_RegI, 15, x15->as_VMReg() ); +reg_def R15_H ( SOC, SOC, Op_RegI, 15, x15->as_VMReg()->next()); +reg_def R16 ( SOC, SOC, Op_RegI, 16, x16->as_VMReg() ); +reg_def R16_H ( SOC, SOC, Op_RegI, 16, x16->as_VMReg()->next()); +reg_def R17 ( SOC, SOC, Op_RegI, 17, x17->as_VMReg() ); +reg_def R17_H ( SOC, SOC, Op_RegI, 17, x17->as_VMReg()->next()); +reg_def R18 ( SOC, SOE, Op_RegI, 18, x18->as_VMReg() ); +reg_def R18_H ( SOC, SOE, Op_RegI, 18, x18->as_VMReg()->next()); +reg_def R19 ( SOC, SOE, Op_RegI, 19, x19->as_VMReg() ); +reg_def R19_H ( SOC, SOE, Op_RegI, 19, x19->as_VMReg()->next()); +reg_def R20 ( SOC, SOE, Op_RegI, 20, x20->as_VMReg() ); // caller esp +reg_def R20_H ( SOC, SOE, Op_RegI, 20, x20->as_VMReg()->next()); +reg_def R21 ( SOC, SOE, Op_RegI, 21, x21->as_VMReg() ); +reg_def R21_H ( SOC, SOE, Op_RegI, 21, x21->as_VMReg()->next()); +reg_def R22 ( SOC, SOE, Op_RegI, 22, x22->as_VMReg() ); +reg_def R22_H ( SOC, SOE, Op_RegI, 22, x22->as_VMReg()->next()); +reg_def R23 ( NS, SOE, Op_RegI, 23, x23->as_VMReg() ); // java thread +reg_def R23_H ( NS, SOE, Op_RegI, 23, x23->as_VMReg()->next()); +reg_def R24 ( SOC, SOE, Op_RegI, 24, x24->as_VMReg() ); +reg_def R24_H ( SOC, SOE, Op_RegI, 24, x24->as_VMReg()->next()); +reg_def R25 ( SOC, SOE, Op_RegI, 25, x25->as_VMReg() ); +reg_def R25_H ( SOC, SOE, Op_RegI, 25, x25->as_VMReg()->next()); +reg_def R26 ( SOC, SOE, Op_RegI, 26, x26->as_VMReg() ); +reg_def R26_H ( SOC, SOE, Op_RegI, 26, x26->as_VMReg()->next()); +reg_def R27 ( SOC, SOE, Op_RegI, 27, x27->as_VMReg() ); // heapbase +reg_def R27_H ( SOC, SOE, Op_RegI, 27, x27->as_VMReg()->next()); +reg_def R28 ( SOC, SOC, Op_RegI, 28, x28->as_VMReg() ); +reg_def R28_H ( SOC, SOC, Op_RegI, 28, x28->as_VMReg()->next()); +reg_def R29 ( SOC, SOC, Op_RegI, 29, x29->as_VMReg() ); +reg_def R29_H ( SOC, SOC, Op_RegI, 29, x29->as_VMReg()->next()); +reg_def R30 ( SOC, SOC, Op_RegI, 30, x30->as_VMReg() ); +reg_def R30_H ( SOC, SOC, Op_RegI, 30, x30->as_VMReg()->next()); +reg_def R31 ( SOC, SOC, Op_RegI, 31, x31->as_VMReg() ); +reg_def R31_H ( SOC, SOC, Op_RegI, 31, x31->as_VMReg()->next()); + +// ---------------------------- +// Float/Double Registers +// ---------------------------- + +// Double Registers + +// The rules of ADL require that double registers be defined in pairs. +// Each pair must be two 32-bit values, but not necessarily a pair of +// single float registers. In each pair, ADLC-assigned register numbers +// must be adjacent, with the lower number even. Finally, when the +// CPU stores such a register pair to memory, the word associated with +// the lower ADLC-assigned number must be stored to the lower address. + +// RISCV has 32 floating-point registers. Each can store a single +// or double precision floating-point value. + +// for Java use float registers f0-f31 are always save on call whereas +// the platform ABI treats f8-f9 and f18-f27 as callee save). Other +// float registers are SOC as per the platform spec + +reg_def F0 ( SOC, SOC, Op_RegF, 0, f0->as_VMReg() ); +reg_def F0_H ( SOC, SOC, Op_RegF, 0, f0->as_VMReg()->next() ); +reg_def F1 ( SOC, SOC, Op_RegF, 1, f1->as_VMReg() ); +reg_def F1_H ( SOC, SOC, Op_RegF, 1, f1->as_VMReg()->next() ); +reg_def F2 ( SOC, SOC, Op_RegF, 2, f2->as_VMReg() ); +reg_def F2_H ( SOC, SOC, Op_RegF, 2, f2->as_VMReg()->next() ); +reg_def F3 ( SOC, SOC, Op_RegF, 3, f3->as_VMReg() ); +reg_def F3_H ( SOC, SOC, Op_RegF, 3, f3->as_VMReg()->next() ); +reg_def F4 ( SOC, SOC, Op_RegF, 4, f4->as_VMReg() ); +reg_def F4_H ( SOC, SOC, Op_RegF, 4, f4->as_VMReg()->next() ); +reg_def F5 ( SOC, SOC, Op_RegF, 5, f5->as_VMReg() ); +reg_def F5_H ( SOC, SOC, Op_RegF, 5, f5->as_VMReg()->next() ); +reg_def F6 ( SOC, SOC, Op_RegF, 6, f6->as_VMReg() ); +reg_def F6_H ( SOC, SOC, Op_RegF, 6, f6->as_VMReg()->next() ); +reg_def F7 ( SOC, SOC, Op_RegF, 7, f7->as_VMReg() ); +reg_def F7_H ( SOC, SOC, Op_RegF, 7, f7->as_VMReg()->next() ); +reg_def F8 ( SOC, SOE, Op_RegF, 8, f8->as_VMReg() ); +reg_def F8_H ( SOC, SOE, Op_RegF, 8, f8->as_VMReg()->next() ); +reg_def F9 ( SOC, SOE, Op_RegF, 9, f9->as_VMReg() ); +reg_def F9_H ( SOC, SOE, Op_RegF, 9, f9->as_VMReg()->next() ); +reg_def F10 ( SOC, SOC, Op_RegF, 10, f10->as_VMReg() ); +reg_def F10_H ( SOC, SOC, Op_RegF, 10, f10->as_VMReg()->next() ); +reg_def F11 ( SOC, SOC, Op_RegF, 11, f11->as_VMReg() ); +reg_def F11_H ( SOC, SOC, Op_RegF, 11, f11->as_VMReg()->next() ); +reg_def F12 ( SOC, SOC, Op_RegF, 12, f12->as_VMReg() ); +reg_def F12_H ( SOC, SOC, Op_RegF, 12, f12->as_VMReg()->next() ); +reg_def F13 ( SOC, SOC, Op_RegF, 13, f13->as_VMReg() ); +reg_def F13_H ( SOC, SOC, Op_RegF, 13, f13->as_VMReg()->next() ); +reg_def F14 ( SOC, SOC, Op_RegF, 14, f14->as_VMReg() ); +reg_def F14_H ( SOC, SOC, Op_RegF, 14, f14->as_VMReg()->next() ); +reg_def F15 ( SOC, SOC, Op_RegF, 15, f15->as_VMReg() ); +reg_def F15_H ( SOC, SOC, Op_RegF, 15, f15->as_VMReg()->next() ); +reg_def F16 ( SOC, SOC, Op_RegF, 16, f16->as_VMReg() ); +reg_def F16_H ( SOC, SOC, Op_RegF, 16, f16->as_VMReg()->next() ); +reg_def F17 ( SOC, SOC, Op_RegF, 17, f17->as_VMReg() ); +reg_def F17_H ( SOC, SOC, Op_RegF, 17, f17->as_VMReg()->next() ); +reg_def F18 ( SOC, SOE, Op_RegF, 18, f18->as_VMReg() ); +reg_def F18_H ( SOC, SOE, Op_RegF, 18, f18->as_VMReg()->next() ); +reg_def F19 ( SOC, SOE, Op_RegF, 19, f19->as_VMReg() ); +reg_def F19_H ( SOC, SOE, Op_RegF, 19, f19->as_VMReg()->next() ); +reg_def F20 ( SOC, SOE, Op_RegF, 20, f20->as_VMReg() ); +reg_def F20_H ( SOC, SOE, Op_RegF, 20, f20->as_VMReg()->next() ); +reg_def F21 ( SOC, SOE, Op_RegF, 21, f21->as_VMReg() ); +reg_def F21_H ( SOC, SOE, Op_RegF, 21, f21->as_VMReg()->next() ); +reg_def F22 ( SOC, SOE, Op_RegF, 22, f22->as_VMReg() ); +reg_def F22_H ( SOC, SOE, Op_RegF, 22, f22->as_VMReg()->next() ); +reg_def F23 ( SOC, SOE, Op_RegF, 23, f23->as_VMReg() ); +reg_def F23_H ( SOC, SOE, Op_RegF, 23, f23->as_VMReg()->next() ); +reg_def F24 ( SOC, SOE, Op_RegF, 24, f24->as_VMReg() ); +reg_def F24_H ( SOC, SOE, Op_RegF, 24, f24->as_VMReg()->next() ); +reg_def F25 ( SOC, SOE, Op_RegF, 25, f25->as_VMReg() ); +reg_def F25_H ( SOC, SOE, Op_RegF, 25, f25->as_VMReg()->next() ); +reg_def F26 ( SOC, SOE, Op_RegF, 26, f26->as_VMReg() ); +reg_def F26_H ( SOC, SOE, Op_RegF, 26, f26->as_VMReg()->next() ); +reg_def F27 ( SOC, SOE, Op_RegF, 27, f27->as_VMReg() ); +reg_def F27_H ( SOC, SOE, Op_RegF, 27, f27->as_VMReg()->next() ); +reg_def F28 ( SOC, SOC, Op_RegF, 28, f28->as_VMReg() ); +reg_def F28_H ( SOC, SOC, Op_RegF, 28, f28->as_VMReg()->next() ); +reg_def F29 ( SOC, SOC, Op_RegF, 29, f29->as_VMReg() ); +reg_def F29_H ( SOC, SOC, Op_RegF, 29, f29->as_VMReg()->next() ); +reg_def F30 ( SOC, SOC, Op_RegF, 30, f30->as_VMReg() ); +reg_def F30_H ( SOC, SOC, Op_RegF, 30, f30->as_VMReg()->next() ); +reg_def F31 ( SOC, SOC, Op_RegF, 31, f31->as_VMReg() ); +reg_def F31_H ( SOC, SOC, Op_RegF, 31, f31->as_VMReg()->next() ); + +// ---------------------------- +// Vector Registers +// ---------------------------- + +// For RVV vector registers, we simply extend vector register size to 4 +// 'logical' slots. This is nominally 128 bits but it actually covers +// all possible 'physical' RVV vector register lengths from 128 ~ 1024 +// bits. The 'physical' RVV vector register length is detected during +// startup, so the register allocator is able to identify the correct +// number of bytes needed for an RVV spill/unspill. + +reg_def V0 ( SOC, SOC, Op_VecA, 0, v0->as_VMReg() ); +reg_def V0_H ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next() ); +reg_def V0_J ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(2) ); +reg_def V0_K ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(3) ); + +reg_def V1 ( SOC, SOC, Op_VecA, 1, v1->as_VMReg() ); +reg_def V1_H ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next() ); +reg_def V1_J ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(2) ); +reg_def V1_K ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(3) ); + +reg_def V2 ( SOC, SOC, Op_VecA, 2, v2->as_VMReg() ); +reg_def V2_H ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next() ); +reg_def V2_J ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(2) ); +reg_def V2_K ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(3) ); + +reg_def V3 ( SOC, SOC, Op_VecA, 3, v3->as_VMReg() ); +reg_def V3_H ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next() ); +reg_def V3_J ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(2) ); +reg_def V3_K ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(3) ); + +reg_def V4 ( SOC, SOC, Op_VecA, 4, v4->as_VMReg() ); +reg_def V4_H ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next() ); +reg_def V4_J ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(2) ); +reg_def V4_K ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(3) ); + +reg_def V5 ( SOC, SOC, Op_VecA, 5, v5->as_VMReg() ); +reg_def V5_H ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next() ); +reg_def V5_J ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(2) ); +reg_def V5_K ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(3) ); + +reg_def V6 ( SOC, SOC, Op_VecA, 6, v6->as_VMReg() ); +reg_def V6_H ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next() ); +reg_def V6_J ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(2) ); +reg_def V6_K ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(3) ); + +reg_def V7 ( SOC, SOC, Op_VecA, 7, v7->as_VMReg() ); +reg_def V7_H ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next() ); +reg_def V7_J ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(2) ); +reg_def V7_K ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(3) ); + +reg_def V8 ( SOC, SOC, Op_VecA, 8, v8->as_VMReg() ); +reg_def V8_H ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next() ); +reg_def V8_J ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(2) ); +reg_def V8_K ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(3) ); + +reg_def V9 ( SOC, SOC, Op_VecA, 9, v9->as_VMReg() ); +reg_def V9_H ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next() ); +reg_def V9_J ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(2) ); +reg_def V9_K ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(3) ); + +reg_def V10 ( SOC, SOC, Op_VecA, 10, v10->as_VMReg() ); +reg_def V10_H ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next() ); +reg_def V10_J ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(2) ); +reg_def V10_K ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(3) ); + +reg_def V11 ( SOC, SOC, Op_VecA, 11, v11->as_VMReg() ); +reg_def V11_H ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next() ); +reg_def V11_J ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(2) ); +reg_def V11_K ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(3) ); + +reg_def V12 ( SOC, SOC, Op_VecA, 12, v12->as_VMReg() ); +reg_def V12_H ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next() ); +reg_def V12_J ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(2) ); +reg_def V12_K ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(3) ); + +reg_def V13 ( SOC, SOC, Op_VecA, 13, v13->as_VMReg() ); +reg_def V13_H ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next() ); +reg_def V13_J ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(2) ); +reg_def V13_K ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(3) ); + +reg_def V14 ( SOC, SOC, Op_VecA, 14, v14->as_VMReg() ); +reg_def V14_H ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next() ); +reg_def V14_J ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(2) ); +reg_def V14_K ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(3) ); + +reg_def V15 ( SOC, SOC, Op_VecA, 15, v15->as_VMReg() ); +reg_def V15_H ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next() ); +reg_def V15_J ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(2) ); +reg_def V15_K ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(3) ); + +reg_def V16 ( SOC, SOC, Op_VecA, 16, v16->as_VMReg() ); +reg_def V16_H ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next() ); +reg_def V16_J ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(2) ); +reg_def V16_K ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(3) ); + +reg_def V17 ( SOC, SOC, Op_VecA, 17, v17->as_VMReg() ); +reg_def V17_H ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next() ); +reg_def V17_J ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(2) ); +reg_def V17_K ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(3) ); + +reg_def V18 ( SOC, SOC, Op_VecA, 18, v18->as_VMReg() ); +reg_def V18_H ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next() ); +reg_def V18_J ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(2) ); +reg_def V18_K ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(3) ); + +reg_def V19 ( SOC, SOC, Op_VecA, 19, v19->as_VMReg() ); +reg_def V19_H ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next() ); +reg_def V19_J ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(2) ); +reg_def V19_K ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(3) ); + +reg_def V20 ( SOC, SOC, Op_VecA, 20, v20->as_VMReg() ); +reg_def V20_H ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next() ); +reg_def V20_J ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(2) ); +reg_def V20_K ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(3) ); + +reg_def V21 ( SOC, SOC, Op_VecA, 21, v21->as_VMReg() ); +reg_def V21_H ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next() ); +reg_def V21_J ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(2) ); +reg_def V21_K ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(3) ); + +reg_def V22 ( SOC, SOC, Op_VecA, 22, v22->as_VMReg() ); +reg_def V22_H ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next() ); +reg_def V22_J ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(2) ); +reg_def V22_K ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(3) ); + +reg_def V23 ( SOC, SOC, Op_VecA, 23, v23->as_VMReg() ); +reg_def V23_H ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next() ); +reg_def V23_J ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(2) ); +reg_def V23_K ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(3) ); + +reg_def V24 ( SOC, SOC, Op_VecA, 24, v24->as_VMReg() ); +reg_def V24_H ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next() ); +reg_def V24_J ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(2) ); +reg_def V24_K ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(3) ); + +reg_def V25 ( SOC, SOC, Op_VecA, 25, v25->as_VMReg() ); +reg_def V25_H ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next() ); +reg_def V25_J ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(2) ); +reg_def V25_K ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(3) ); + +reg_def V26 ( SOC, SOC, Op_VecA, 26, v26->as_VMReg() ); +reg_def V26_H ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next() ); +reg_def V26_J ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(2) ); +reg_def V26_K ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(3) ); + +reg_def V27 ( SOC, SOC, Op_VecA, 27, v27->as_VMReg() ); +reg_def V27_H ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next() ); +reg_def V27_J ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(2) ); +reg_def V27_K ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(3) ); + +reg_def V28 ( SOC, SOC, Op_VecA, 28, v28->as_VMReg() ); +reg_def V28_H ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next() ); +reg_def V28_J ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(2) ); +reg_def V28_K ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(3) ); + +reg_def V29 ( SOC, SOC, Op_VecA, 29, v29->as_VMReg() ); +reg_def V29_H ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next() ); +reg_def V29_J ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(2) ); +reg_def V29_K ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(3) ); + +reg_def V30 ( SOC, SOC, Op_VecA, 30, v30->as_VMReg() ); +reg_def V30_H ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next() ); +reg_def V30_J ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(2) ); +reg_def V30_K ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(3) ); + +reg_def V31 ( SOC, SOC, Op_VecA, 31, v31->as_VMReg() ); +reg_def V31_H ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next() ); +reg_def V31_J ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(2) ); +reg_def V31_K ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(3) ); + +// ---------------------------- +// Special Registers +// ---------------------------- + +// On riscv, the physical flag register is missing, so we use t1 instead, +// to bridge the RegFlag semantics in share/opto + +reg_def RFLAGS (SOC, SOC, Op_RegFlags, 6, x6->as_VMReg() ); + +// Specify priority of register selection within phases of register +// allocation. Highest priority is first. A useful heuristic is to +// give registers a low priority when they are required by machine +// instructions, like EAX and EDX on I486, and choose no-save registers +// before save-on-call, & save-on-call before save-on-entry. Registers +// which participate in fixed calling sequences should come last. +// Registers which are used as pairs must fall on an even boundary. + +alloc_class chunk0( + // volatiles + R7, R7_H, + R28, R28_H, + R29, R29_H, + R30, R30_H, + R31, R31_H, + + // arg registers + R10, R10_H, + R11, R11_H, + R12, R12_H, + R13, R13_H, + R14, R14_H, + R15, R15_H, + R16, R16_H, + R17, R17_H, + + // non-volatiles + R9, R9_H, + R18, R18_H, + R19, R19_H, + R20, R20_H, + R21, R21_H, + R22, R22_H, + R24, R24_H, + R25, R25_H, + R26, R26_H, + + // non-allocatable registers + R23, R23_H, // java thread + R27, R27_H, // heapbase + R4, R4_H, // thread + R8, R8_H, // fp + R0, R0_H, // zero + R1, R1_H, // ra + R2, R2_H, // sp + R3, R3_H, // gp +); + +alloc_class chunk1( + + // no save + F0, F0_H, + F1, F1_H, + F2, F2_H, + F3, F3_H, + F4, F4_H, + F5, F5_H, + F6, F6_H, + F7, F7_H, + F28, F28_H, + F29, F29_H, + F30, F30_H, + F31, F31_H, + + // arg registers + F10, F10_H, + F11, F11_H, + F12, F12_H, + F13, F13_H, + F14, F14_H, + F15, F15_H, + F16, F16_H, + F17, F17_H, + + // non-volatiles + F8, F8_H, + F9, F9_H, + F18, F18_H, + F19, F19_H, + F20, F20_H, + F21, F21_H, + F22, F22_H, + F23, F23_H, + F24, F24_H, + F25, F25_H, + F26, F26_H, + F27, F27_H, +); + +alloc_class chunk2( + V0, V0_H, V0_J, V0_K, + V1, V1_H, V1_J, V1_K, + V2, V2_H, V2_J, V2_K, + V3, V3_H, V3_J, V3_K, + V4, V4_H, V4_J, V4_K, + V5, V5_H, V5_J, V5_K, + V6, V6_H, V6_J, V6_K, + V7, V7_H, V7_J, V7_K, + V8, V8_H, V8_J, V8_K, + V9, V9_H, V9_J, V9_K, + V10, V10_H, V10_J, V10_K, + V11, V11_H, V11_J, V11_K, + V12, V12_H, V12_J, V12_K, + V13, V13_H, V13_J, V13_K, + V14, V14_H, V14_J, V14_K, + V15, V15_H, V15_J, V15_K, + V16, V16_H, V16_J, V16_K, + V17, V17_H, V17_J, V17_K, + V18, V18_H, V18_J, V18_K, + V19, V19_H, V19_J, V19_K, + V20, V20_H, V20_J, V20_K, + V21, V21_H, V21_J, V21_K, + V22, V22_H, V22_J, V22_K, + V23, V23_H, V23_J, V23_K, + V24, V24_H, V24_J, V24_K, + V25, V25_H, V25_J, V25_K, + V26, V26_H, V26_J, V26_K, + V27, V27_H, V27_J, V27_K, + V28, V28_H, V28_J, V28_K, + V29, V29_H, V29_J, V29_K, + V30, V30_H, V30_J, V30_K, + V31, V31_H, V31_J, V31_K, +); + +alloc_class chunk3(RFLAGS); + +//----------Architecture Description Register Classes-------------------------- +// Several register classes are automatically defined based upon information in +// this architecture description. +// 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) +// 2) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) +// + +// Class for all 32 bit general purpose registers +reg_class all_reg32( + R0, + R1, + R2, + R3, + R4, + R7, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + R16, + R17, + R18, + R19, + R20, + R21, + R22, + R23, + R24, + R25, + R26, + R27, + R28, + R29, + R30, + R31 +); + +// Class for any 32 bit integer registers (excluding zr) +reg_class any_reg32 %{ + return _ANY_REG32_mask; +%} + +// Singleton class for R10 int register +reg_class int_r10_reg(R10); + +// Singleton class for R12 int register +reg_class int_r12_reg(R12); + +// Singleton class for R13 int register +reg_class int_r13_reg(R13); + +// Singleton class for R14 int register +reg_class int_r14_reg(R14); + +// Class for all long integer registers +reg_class all_reg( + R0, R0_H, + R1, R1_H, + R2, R2_H, + R3, R3_H, + R4, R4_H, + R7, R7_H, + R8, R8_H, + R9, R9_H, + R10, R10_H, + R11, R11_H, + R12, R12_H, + R13, R13_H, + R14, R14_H, + R15, R15_H, + R16, R16_H, + R17, R17_H, + R18, R18_H, + R19, R19_H, + R20, R20_H, + R21, R21_H, + R22, R22_H, + R23, R23_H, + R24, R24_H, + R25, R25_H, + R26, R26_H, + R27, R27_H, + R28, R28_H, + R29, R29_H, + R30, R30_H, + R31, R31_H +); + +// Class for all long integer registers (excluding zr) +reg_class any_reg %{ + return _ANY_REG_mask; +%} + +// Class for non-allocatable 32 bit registers +reg_class non_allocatable_reg32( + R0, // zr + R1, // ra + R2, // sp + R3, // gp + R4, // tp + R23 // java thread +); + +// Class for non-allocatable 64 bit registers +reg_class non_allocatable_reg( + R0, R0_H, // zr + R1, R1_H, // ra + R2, R2_H, // sp + R3, R3_H, // gp + R4, R4_H, // tp + R23, R23_H // java thread +); + +reg_class no_special_reg32 %{ + return _NO_SPECIAL_REG32_mask; +%} + +reg_class no_special_reg %{ + return _NO_SPECIAL_REG_mask; +%} + +reg_class ptr_reg %{ + return _PTR_REG_mask; +%} + +reg_class no_special_ptr_reg %{ + return _NO_SPECIAL_PTR_REG_mask; +%} + +// Class for 64 bit register r10 +reg_class r10_reg( + R10, R10_H +); + +// Class for 64 bit register r11 +reg_class r11_reg( + R11, R11_H +); + +// Class for 64 bit register r12 +reg_class r12_reg( + R12, R12_H +); + +// Class for 64 bit register r13 +reg_class r13_reg( + R13, R13_H +); + +// Class for 64 bit register r14 +reg_class r14_reg( + R14, R14_H +); + +// Class for 64 bit register r15 +reg_class r15_reg( + R15, R15_H +); + +// Class for 64 bit register r16 +reg_class r16_reg( + R16, R16_H +); + +// Class for method register +reg_class method_reg( + R31, R31_H +); + +// Class for heapbase register +reg_class heapbase_reg( + R27, R27_H +); + +// Class for java thread register +reg_class java_thread_reg( + R23, R23_H +); + +reg_class r28_reg( + R28, R28_H +); + +reg_class r29_reg( + R29, R29_H +); + +reg_class r30_reg( + R30, R30_H +); + +// Class for zero registesr +reg_class zr_reg( + R0, R0_H +); + +// Class for thread register +reg_class thread_reg( + R4, R4_H +); + +// Class for frame pointer register +reg_class fp_reg( + R8, R8_H +); + +// Class for link register +reg_class ra_reg( + R1, R1_H +); + +// Class for long sp register +reg_class sp_reg( + R2, R2_H +); + +// Class for all float registers +reg_class float_reg( + F0, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + F25, + F26, + F27, + F28, + F29, + F30, + F31 +); + +// Double precision float registers have virtual `high halves' that +// are needed by the allocator. +// Class for all double registers +reg_class double_reg( + F0, F0_H, + F1, F1_H, + F2, F2_H, + F3, F3_H, + F4, F4_H, + F5, F5_H, + F6, F6_H, + F7, F7_H, + F8, F8_H, + F9, F9_H, + F10, F10_H, + F11, F11_H, + F12, F12_H, + F13, F13_H, + F14, F14_H, + F15, F15_H, + F16, F16_H, + F17, F17_H, + F18, F18_H, + F19, F19_H, + F20, F20_H, + F21, F21_H, + F22, F22_H, + F23, F23_H, + F24, F24_H, + F25, F25_H, + F26, F26_H, + F27, F27_H, + F28, F28_H, + F29, F29_H, + F30, F30_H, + F31, F31_H +); + +// Class for all RVV vector registers +reg_class vectora_reg( + V1, V1_H, V1_J, V1_K, + V2, V2_H, V2_J, V2_K, + V3, V3_H, V3_J, V3_K, + V4, V4_H, V4_J, V4_K, + V5, V5_H, V5_J, V5_K, + V6, V6_H, V6_J, V6_K, + V7, V7_H, V7_J, V7_K, + V8, V8_H, V8_J, V8_K, + V9, V9_H, V9_J, V9_K, + V10, V10_H, V10_J, V10_K, + V11, V11_H, V11_J, V11_K, + V12, V12_H, V12_J, V12_K, + V13, V13_H, V13_J, V13_K, + V14, V14_H, V14_J, V14_K, + V15, V15_H, V15_J, V15_K, + V16, V16_H, V16_J, V16_K, + V17, V17_H, V17_J, V17_K, + V18, V18_H, V18_J, V18_K, + V19, V19_H, V19_J, V19_K, + V20, V20_H, V20_J, V20_K, + V21, V21_H, V21_J, V21_K, + V22, V22_H, V22_J, V22_K, + V23, V23_H, V23_J, V23_K, + V24, V24_H, V24_J, V24_K, + V25, V25_H, V25_J, V25_K, + V26, V26_H, V26_J, V26_K, + V27, V27_H, V27_J, V27_K, + V28, V28_H, V28_J, V28_K, + V29, V29_H, V29_J, V29_K, + V30, V30_H, V30_J, V30_K, + V31, V31_H, V31_J, V31_K +); + +// Class for 64 bit register f0 +reg_class f0_reg( + F0, F0_H +); + +// Class for 64 bit register f1 +reg_class f1_reg( + F1, F1_H +); + +// Class for 64 bit register f2 +reg_class f2_reg( + F2, F2_H +); + +// Class for 64 bit register f3 +reg_class f3_reg( + F3, F3_H +); + +// class for vector register v1 +reg_class v1_reg( + V1, V1_H, V1_J, V1_K +); + +// class for vector register v2 +reg_class v2_reg( + V2, V2_H, V2_J, V2_K +); + +// class for vector register v3 +reg_class v3_reg( + V3, V3_H, V3_J, V3_K +); + +// class for vector register v4 +reg_class v4_reg( + V4, V4_H, V4_J, V4_K +); + +// class for vector register v5 +reg_class v5_reg( + V5, V5_H, V5_J, V5_K +); + +// class for condition codes +reg_class reg_flags(RFLAGS); +%} + +//----------DEFINITION BLOCK--------------------------------------------------- +// Define name --> value mappings to inform the ADLC of an integer valued name +// Current support includes integer values in the range [0, 0x7FFFFFFF] +// Format: +// int_def ( , ); +// Generated Code in ad_.hpp +// #define () +// // value == +// Generated code in ad_.cpp adlc_verification() +// assert( == , "Expect () to equal "); +// + +// we follow the ppc-aix port in using a simple cost model which ranks +// register operations as cheap, memory ops as more expensive and +// branches as most expensive. the first two have a low as well as a +// normal cost. huge cost appears to be a way of saying don't do +// something + +definitions %{ + // The default cost (of a register move instruction). + int_def DEFAULT_COST ( 100, 100); + int_def ALU_COST ( 100, 1 * DEFAULT_COST); // unknown, const, arith, shift, slt, + // multi, auipc, nop, logical, move + int_def LOAD_COST ( 300, 3 * DEFAULT_COST); // load, fpload + int_def STORE_COST ( 100, 1 * DEFAULT_COST); // store, fpstore + int_def XFER_COST ( 300, 3 * DEFAULT_COST); // mfc, mtc, fcvt, fmove, fcmp + int_def BRANCH_COST ( 100, 1 * DEFAULT_COST); // branch, jmp, call + int_def IMUL_COST ( 1000, 10 * DEFAULT_COST); // imul + int_def IDIVSI_COST ( 3400, 34 * DEFAULT_COST); // idivdi + int_def IDIVDI_COST ( 6600, 66 * DEFAULT_COST); // idivsi + int_def FMUL_SINGLE_COST ( 500, 5 * DEFAULT_COST); // fadd, fmul, fmadd + int_def FMUL_DOUBLE_COST ( 700, 7 * DEFAULT_COST); // fadd, fmul, fmadd + int_def FDIV_COST ( 2000, 20 * DEFAULT_COST); // fdiv + int_def FSQRT_COST ( 2500, 25 * DEFAULT_COST); // fsqrt + int_def VOLATILE_REF_COST ( 1000, 10 * DEFAULT_COST); +%} + + + +//----------SOURCE BLOCK------------------------------------------------------- +// This is a block of C++ code which provides values, functions, and +// definitions necessary in the rest of the architecture description + +source_hpp %{ + +#include "asm/macroAssembler.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "opto/addnode.hpp" +#include "opto/convertnode.hpp" + +extern RegMask _ANY_REG32_mask; +extern RegMask _ANY_REG_mask; +extern RegMask _PTR_REG_mask; +extern RegMask _NO_SPECIAL_REG32_mask; +extern RegMask _NO_SPECIAL_REG_mask; +extern RegMask _NO_SPECIAL_PTR_REG_mask; + +class CallStubImpl { + + //-------------------------------------------------------------- + //---< Used for optimization in Compile::shorten_branches >--- + //-------------------------------------------------------------- + + public: + // Size of call trampoline stub. + static uint size_call_trampoline() { + return 0; // no call trampolines on this platform + } + + // number of relocations needed by a call trampoline stub + static uint reloc_call_trampoline() { + return 0; // no call trampolines on this platform + } +}; + +class HandlerImpl { + + public: + + static int emit_exception_handler(CodeBuffer &cbuf); + static int emit_deopt_handler(CodeBuffer& cbuf); + + static uint size_exception_handler() { + return MacroAssembler::far_branch_size(); + } + + static uint size_deopt_handler() { + // count auipc + far branch + return NativeInstruction::instruction_size + MacroAssembler::far_branch_size(); + } +}; + +class Node::PD { +public: + enum NodeFlags { + _last_flag = Node::_last_flag + }; +}; + +bool is_CAS(int opcode, bool maybe_volatile); + +// predicate controlling translation of CompareAndSwapX +bool needs_acquiring_load_reserved(const Node *load); + +// predicate controlling addressing modes +bool size_fits_all_mem_uses(AddPNode* addp, int shift); +%} + +source %{ + +// Derived RegMask with conditionally allocatable registers + +RegMask _ANY_REG32_mask; +RegMask _ANY_REG_mask; +RegMask _PTR_REG_mask; +RegMask _NO_SPECIAL_REG32_mask; +RegMask _NO_SPECIAL_REG_mask; +RegMask _NO_SPECIAL_PTR_REG_mask; + +void reg_mask_init() { + + _ANY_REG32_mask = _ALL_REG32_mask; + _ANY_REG32_mask.Remove(OptoReg::as_OptoReg(x0->as_VMReg())); + + _ANY_REG_mask = _ALL_REG_mask; + _ANY_REG_mask.SUBTRACT(_ZR_REG_mask); + + _PTR_REG_mask = _ALL_REG_mask; + _PTR_REG_mask.SUBTRACT(_ZR_REG_mask); + + _NO_SPECIAL_REG32_mask = _ALL_REG32_mask; + _NO_SPECIAL_REG32_mask.SUBTRACT(_NON_ALLOCATABLE_REG32_mask); + + _NO_SPECIAL_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); + + _NO_SPECIAL_PTR_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); + + // x27 is not allocatable when compressed oops is on + if (UseCompressedOops) { + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(x27->as_VMReg())); + _NO_SPECIAL_REG_mask.SUBTRACT(_HEAPBASE_REG_mask); + _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_HEAPBASE_REG_mask); + } + + // x8 is not allocatable when PreserveFramePointer is on + if (PreserveFramePointer) { + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); + _NO_SPECIAL_REG_mask.SUBTRACT(_FP_REG_mask); + _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_FP_REG_mask); + } +} + +void PhaseOutput::pd_perform_mach_node_analysis() { +} + +int MachNode::pd_alignment_required() const { + return 1; +} + +int MachNode::compute_padding(int current_offset) const { + return 0; +} + +// is_CAS(int opcode, bool maybe_volatile) +// +// return true if opcode is one of the possible CompareAndSwapX +// values otherwise false. +bool is_CAS(int opcode, bool maybe_volatile) +{ + switch (opcode) { + // We handle these + case Op_CompareAndSwapI: + case Op_CompareAndSwapL: + case Op_CompareAndSwapP: + case Op_CompareAndSwapN: + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: + case Op_CompareAndSwapB: + case Op_CompareAndSwapS: + case Op_GetAndSetI: + case Op_GetAndSetL: + case Op_GetAndSetP: + case Op_GetAndSetN: + case Op_GetAndAddI: + case Op_GetAndAddL: + return true; + case Op_CompareAndExchangeI: + case Op_CompareAndExchangeN: + case Op_CompareAndExchangeB: + case Op_CompareAndExchangeS: + case Op_CompareAndExchangeL: + case Op_CompareAndExchangeP: + case Op_WeakCompareAndSwapB: + case Op_WeakCompareAndSwapS: + case Op_WeakCompareAndSwapI: + case Op_WeakCompareAndSwapL: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahWeakCompareAndSwapN: + case Op_ShenandoahCompareAndExchangeP: + case Op_ShenandoahCompareAndExchangeN: + return maybe_volatile; + default: + return false; + } +} + +// predicate controlling translation of CAS +// +// returns true if CAS needs to use an acquiring load otherwise false +bool needs_acquiring_load_reserved(const Node *n) +{ + assert(n != NULL && is_CAS(n->Opcode(), true), "expecting a compare and swap"); + + LoadStoreNode* ldst = n->as_LoadStore(); + if (n != NULL && is_CAS(n->Opcode(), false)) { + assert(ldst != NULL && ldst->trailing_membar() != NULL, "expected trailing membar"); + } else { + return ldst != NULL && ldst->trailing_membar() != NULL; + } + // so we can just return true here + return true; +} +#define __ _masm. + +// advance declarations for helper functions to convert register +// indices to register objects + +// the ad file has to provide implementations of certain methods +// expected by the generic code +// +// REQUIRED FUNCTIONALITY + +//============================================================================= + +// !!!!! Special hack to get all types of calls to specify the byte offset +// from the start of the call to the point where the return address +// will point. + +int MachCallStaticJavaNode::ret_addr_offset() +{ + // jal + return 1 * NativeInstruction::instruction_size; +} + +int MachCallDynamicJavaNode::ret_addr_offset() +{ + return 7 * NativeInstruction::instruction_size; // movptr, jal +} + +int MachCallRuntimeNode::ret_addr_offset() { + // for generated stubs the call will be + // jal(addr) + // or with far branches + // jal(trampoline_stub) + // for real runtime callouts it will be 11 instructions + // see riscv_enc_java_to_runtime + // la(t1, retaddr) -> auipc + addi + // la(t0, RuntimeAddress(addr)) -> lui + addi + slli + addi + slli + addi + // addi(sp, sp, -2 * wordSize) -> addi + // sd(t1, Address(sp, wordSize)) -> sd + // jalr(t0) -> jalr + CodeBlob *cb = CodeCache::find_blob(_entry_point); + if (cb != NULL) { + return 1 * NativeInstruction::instruction_size; + } else { + return 11 * NativeInstruction::instruction_size; + } +} + +int MachCallNativeNode::ret_addr_offset() { + Unimplemented(); + return -1; +} + +// +// Compute padding required for nodes which need alignment +// + +// With RVC a call instruction may get 2-byte aligned. +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. +int CallStaticJavaDirectNode::compute_padding(int current_offset) const +{ + // to make sure the address of jal 4-byte aligned. + return align_up(current_offset, alignment_required()) - current_offset; +} + +// With RVC a call instruction may get 2-byte aligned. +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. +int CallDynamicJavaDirectNode::compute_padding(int current_offset) const +{ + // skip the movptr in MacroAssembler::ic_call(): + // lui + addi + slli + addi + slli + addi + // Though movptr() has already 4-byte aligned with or without RVC, + // We need to prevent from further changes by explicitly calculating the size. + const int movptr_size = 6 * NativeInstruction::instruction_size; + current_offset += movptr_size; + // to make sure the address of jal 4-byte aligned. + return align_up(current_offset, alignment_required()) - current_offset; +} + +//============================================================================= + +#ifndef PRODUCT +void MachBreakpointNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + assert_cond(st != NULL); + st->print("BREAKPOINT"); +} +#endif + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + __ ebreak(); +} + +uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { + return MachNode::size(ra_); +} + +//============================================================================= + +#ifndef PRODUCT + void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const { + st->print("nop \t# %d bytes pad for loops and calls", _count); + } +#endif + + void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const { + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); // nops shall be 2-byte under RVC for alignment purposes. + for (int i = 0; i < _count; i++) { + __ nop(); + } + } + + uint MachNopNode::size(PhaseRegAlloc*) const { + return _count * (UseRVC ? NativeInstruction::compressed_instruction_size : NativeInstruction::instruction_size); + } + +//============================================================================= +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; + +int ConstantTable::calculate_table_base_offset() const { + return 0; // absolute addressing, no offset +} + +bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } +void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { + ShouldNotReachHere(); +} + +void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + // Empty encoding +} + +uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { + return 0; +} + +#ifndef PRODUCT +void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { + assert_cond(st != NULL); + st->print("-- \t// MachConstantBaseNode (empty encoding)"); +} +#endif + +#ifndef PRODUCT +void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + assert_cond(st != NULL && ra_ != NULL); + Compile* C = ra_->C; + + int framesize = C->output()->frame_slots() << LogBytesPerInt; + + if (C->output()->need_stack_bang(framesize)) { + st->print("# stack bang size=%d\n\t", framesize); + } + + st->print("sd fp, [sp, #%d]\n\t", - 2 * wordSize); + st->print("sd ra, [sp, #%d]\n\t", - wordSize); + if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); } + st->print("sub sp, sp, #%d\n\t", framesize); + + if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { + st->print("ld t0, [guard]\n\t"); + st->print("membar LoadLoad\n\t"); + st->print("ld t1, [xthread, #thread_disarmed_offset]\n\t"); + st->print("beq t0, t1, skip\n\t"); + st->print("jalr #nmethod_entry_barrier_stub\n\t"); + st->print("j skip\n\t"); + st->print("guard: int\n\t"); + st->print("skip:\n\t"); + } +} +#endif + +void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + assert_cond(ra_ != NULL); + Compile* C = ra_->C; + C2_MacroAssembler _masm(&cbuf); + + // n.b. frame size includes space for return pc and fp + const int framesize = C->output()->frame_size_in_bytes(); + + // insert a nop at the start of the prolog so we can patch in a + // branch if we need to invalidate the method later + __ nop(); + + assert_cond(C != NULL); + + if (C->clinit_barrier_on_entry()) { + assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started"); + + Label L_skip_barrier; + + __ mov_metadata(t1, C->method()->holder()->constant_encoding()); + __ clinit_barrier(t1, t0, &L_skip_barrier); + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + __ bind(L_skip_barrier); + } + + int bangsize = C->output()->bang_size_in_bytes(); + if (C->output()->need_stack_bang(bangsize)) { + __ generate_stack_overflow_check(bangsize); + } + + __ build_frame(framesize); + + if (C->stub_function() == NULL) { + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(&_masm); + } + + if (VerifyStackAtCalls) { + Unimplemented(); + } + + C->output()->set_frame_complete(cbuf.insts_size()); + + if (C->has_mach_constant_base_node()) { + // NOTE: We set the table base offset here because users might be + // emitted before MachConstantBaseNode. + ConstantTable& constant_table = C->output()->constant_table(); + constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); + } +} + +uint MachPrologNode::size(PhaseRegAlloc* ra_) const +{ + assert_cond(ra_ != NULL); + return MachNode::size(ra_); // too many variables; just compute it + // the hard way +} + +int MachPrologNode::reloc() const +{ + return 0; +} + +//============================================================================= + +#ifndef PRODUCT +void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + assert_cond(st != NULL && ra_ != NULL); + Compile* C = ra_->C; + assert_cond(C != NULL); + int framesize = C->output()->frame_size_in_bytes(); + + st->print("# pop frame %d\n\t", framesize); + + if (framesize == 0) { + st->print("ld ra, [sp,#%d]\n\t", (2 * wordSize)); + st->print("ld fp, [sp,#%d]\n\t", (3 * wordSize)); + st->print("add sp, sp, #%d\n\t", (2 * wordSize)); + } else { + st->print("add sp, sp, #%d\n\t", framesize); + st->print("ld ra, [sp,#%d]\n\t", - 2 * wordSize); + st->print("ld fp, [sp,#%d]\n\t", - wordSize); + } + + if (do_polling() && C->is_method_compilation()) { + st->print("# test polling word\n\t"); + st->print("ld t0, [xthread,#%d]\n\t", in_bytes(JavaThread::polling_word_offset())); + st->print("bgtu sp, t0, #slow_path"); + } +} +#endif + +void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + assert_cond(ra_ != NULL); + Compile* C = ra_->C; + C2_MacroAssembler _masm(&cbuf); + assert_cond(C != NULL); + int framesize = C->output()->frame_size_in_bytes(); + + __ remove_frame(framesize); + + if (StackReservedPages > 0 && C->has_reserved_stack_access()) { + __ reserved_stack_check(); + } + + if (do_polling() && C->is_method_compilation()) { + Label dummy_label; + Label* code_stub = &dummy_label; + if (!C->output()->in_scratch_emit_size()) { + code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + } + __ relocate(relocInfo::poll_return_type); + __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); + } +} + +uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { + assert_cond(ra_ != NULL); + // Variable size. Determine dynamically. + return MachNode::size(ra_); +} + +int MachEpilogNode::reloc() const { + // Return number of relocatable values contained in this instruction. + return 1; // 1 for polling page. +} +const Pipeline * MachEpilogNode::pipeline() const { + return MachNode::pipeline_class(); +} + +//============================================================================= + +// Figure out which register class each belongs in: rc_int, rc_float or +// rc_stack. +enum RC { rc_bad, rc_int, rc_float, rc_vector, rc_stack }; + +static enum RC rc_class(OptoReg::Name reg) { + + if (reg == OptoReg::Bad) { + return rc_bad; + } + + // we have 30 int registers * 2 halves + // (t0 and t1 are omitted) + int slots_of_int_registers = RegisterImpl::max_slots_per_register * (RegisterImpl::number_of_registers - 2); + if (reg < slots_of_int_registers) { + return rc_int; + } + + // we have 32 float register * 2 halves + int slots_of_float_registers = FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers; + if (reg < slots_of_int_registers + slots_of_float_registers) { + return rc_float; + } + + // we have 32 vector register * 4 halves + int slots_of_vector_registers = VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers; + if (reg < slots_of_int_registers + slots_of_float_registers + slots_of_vector_registers) { + return rc_vector; + } + + // Between vector regs & stack is the flags regs. + assert(OptoReg::is_stack(reg), "blow up if spilling flags"); + + return rc_stack; +} + +uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream *st) const { + assert_cond(ra_ != NULL); + Compile* C = ra_->C; + + // Get registers to move. + OptoReg::Name src_hi = ra_->get_reg_second(in(1)); + OptoReg::Name src_lo = ra_->get_reg_first(in(1)); + OptoReg::Name dst_hi = ra_->get_reg_second(this); + OptoReg::Name dst_lo = ra_->get_reg_first(this); + + enum RC src_hi_rc = rc_class(src_hi); + enum RC src_lo_rc = rc_class(src_lo); + enum RC dst_hi_rc = rc_class(dst_hi); + enum RC dst_lo_rc = rc_class(dst_lo); + + assert(src_lo != OptoReg::Bad && dst_lo != OptoReg::Bad, "must move at least 1 register"); + + if (src_hi != OptoReg::Bad) { + assert((src_lo & 1) == 0 && src_lo + 1 == src_hi && + (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi, + "expected aligned-adjacent pairs"); + } + + if (src_lo == dst_lo && src_hi == dst_hi) { + return 0; // Self copy, no move. + } + + bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi && + (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi; + int src_offset = ra_->reg2offset(src_lo); + int dst_offset = ra_->reg2offset(dst_lo); + + if (bottom_type()->isa_vect() != NULL) { + uint ireg = ideal_reg(); + if (ireg == Op_VecA && cbuf) { + C2_MacroAssembler _masm(cbuf); + Assembler::CompressibleRegion cr(&_masm); + int vector_reg_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); + if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { + // stack to stack + __ spill_copy_vector_stack_to_stack(src_offset, dst_offset, + vector_reg_size_in_bytes); + } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) { + // vpr to stack + __ spill(as_VectorRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo)); + } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) { + // stack to vpr + __ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo)); + } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) { + // vpr to vpr + __ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo])); + } else { + ShouldNotReachHere(); + } + } + } else if (cbuf != NULL) { + C2_MacroAssembler _masm(cbuf); + Assembler::CompressibleRegion cr(&_masm); + switch (src_lo_rc) { + case rc_int: + if (dst_lo_rc == rc_int) { // gpr --> gpr copy + if (!is64 && this->ideal_reg() != Op_RegI) { // zero extended for narrow oop or klass + __ zero_extend(as_Register(Matcher::_regEncode[dst_lo]), as_Register(Matcher::_regEncode[src_lo]), 32); + } else { + __ mv(as_Register(Matcher::_regEncode[dst_lo]), as_Register(Matcher::_regEncode[src_lo])); + } + } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy + if (is64) { + __ fmv_d_x(as_FloatRegister(Matcher::_regEncode[dst_lo]), + as_Register(Matcher::_regEncode[src_lo])); + } else { + __ fmv_w_x(as_FloatRegister(Matcher::_regEncode[dst_lo]), + as_Register(Matcher::_regEncode[src_lo])); + } + } else { // gpr --> stack spill + assert(dst_lo_rc == rc_stack, "spill to bad register class"); + __ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset); + } + break; + case rc_float: + if (dst_lo_rc == rc_int) { // fpr --> gpr copy + if (is64) { + __ fmv_x_d(as_Register(Matcher::_regEncode[dst_lo]), + as_FloatRegister(Matcher::_regEncode[src_lo])); + } else { + __ fmv_x_w(as_Register(Matcher::_regEncode[dst_lo]), + as_FloatRegister(Matcher::_regEncode[src_lo])); + } + } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy + if (is64) { + __ fmv_d(as_FloatRegister(Matcher::_regEncode[dst_lo]), + as_FloatRegister(Matcher::_regEncode[src_lo])); + } else { + __ fmv_s(as_FloatRegister(Matcher::_regEncode[dst_lo]), + as_FloatRegister(Matcher::_regEncode[src_lo])); + } + } else { // fpr --> stack spill + assert(dst_lo_rc == rc_stack, "spill to bad register class"); + __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]), + is64, dst_offset); + } + break; + case rc_stack: + if (dst_lo_rc == rc_int) { // stack --> gpr load + if (this->ideal_reg() == Op_RegI) { + __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset); + } else { // // zero extended for narrow oop or klass + __ unspillu(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset); + } + } else if (dst_lo_rc == rc_float) { // stack --> fpr load + __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]), + is64, src_offset); + } else { // stack --> stack copy + assert(dst_lo_rc == rc_stack, "spill to bad register class"); + if (this->ideal_reg() == Op_RegI) { + __ unspill(t0, is64, src_offset); + } else { // zero extended for narrow oop or klass + __ unspillu(t0, is64, src_offset); + } + __ spill(t0, is64, dst_offset); + } + break; + default: + ShouldNotReachHere(); + } + } + + if (st != NULL) { + st->print("spill "); + if (src_lo_rc == rc_stack) { + st->print("[sp, #%d] -> ", src_offset); + } else { + st->print("%s -> ", Matcher::regName[src_lo]); + } + if (dst_lo_rc == rc_stack) { + st->print("[sp, #%d]", dst_offset); + } else { + st->print("%s", Matcher::regName[dst_lo]); + } + if (bottom_type()->isa_vect() != NULL) { + int vsize = 0; + if (ideal_reg() == Op_VecA) { + vsize = Matcher::scalable_vector_reg_size(T_BYTE) * 8; + } else { + ShouldNotReachHere(); + } + st->print("\t# vector spill size = %d", vsize); + } else { + st->print("\t# spill size = %d", is64 ? 64 : 32); + } + } + + return 0; +} + +#ifndef PRODUCT +void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + if (ra_ == NULL) { + st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx); + } else { + implementation(NULL, ra_, false, st); + } +} +#endif + +void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + implementation(&cbuf, ra_, false, NULL); +} + +uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { + return MachNode::size(ra_); +} + +//============================================================================= + +#ifndef PRODUCT +void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + assert_cond(ra_ != NULL && st != NULL); + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + int reg = ra_->get_reg_first(this); + st->print("add %s, sp, #%d\t# box lock", + Matcher::regName[reg], offset); +} +#endif + +void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + C2_MacroAssembler _masm(&cbuf); + + assert_cond(ra_ != NULL); + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + int reg = ra_->get_encode(this); + + if (is_imm_in_range(offset, 12, 0)) { + __ addi(as_Register(reg), sp, offset); + } else if (is_imm_in_range(offset, 32, 0)) { + __ li32(t0, offset); + __ add(as_Register(reg), sp, t0); + } else { + ShouldNotReachHere(); + } +} + +uint BoxLockNode::size(PhaseRegAlloc *ra_) const { + // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_). + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + + if (is_imm_in_range(offset, 12, 0)) { + return NativeInstruction::instruction_size; + } else { + return 3 * NativeInstruction::instruction_size; // lui + addiw + add; + } +} + +//============================================================================= + +#ifndef PRODUCT +void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const +{ + assert_cond(st != NULL); + st->print_cr("# MachUEPNode"); + if (UseCompressedClassPointers) { + st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + if (CompressedKlassPointers::shift() != 0) { + st->print_cr("\tdecode_klass_not_null t0, t0"); + } + } else { + st->print_cr("\tld t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + } + st->print_cr("\tbeq t0, t1, ic_hit"); + st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check"); + st->print_cr("\tic_hit:"); +} +#endif + +void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const +{ + // This is the unverified entry point. + C2_MacroAssembler _masm(&cbuf); + + Label skip; + __ cmp_klass(j_rarg0, t1, t0, skip); + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + __ bind(skip); +} + +uint MachUEPNode::size(PhaseRegAlloc* ra_) const +{ + assert_cond(ra_ != NULL); + return MachNode::size(ra_); +} + +// REQUIRED EMIT CODE + +//============================================================================= + +// Emit exception handler code. +int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) +{ + // la_patchable t0, #exception_blob_entry_point + // jr (offset)t0 + // or + // j #exception_blob_entry_point + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. + C2_MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_exception_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } + int offset = __ offset(); + __ far_jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); + assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); + __ end_a_stub(); + return offset; +} + +// Emit deopt handler code. +int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) +{ + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. + C2_MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_deopt_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } + int offset = __ offset(); + + __ auipc(ra, 0); + __ far_jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); + + assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); + __ end_a_stub(); + return offset; + +} +// REQUIRED MATCHER CODE + +//============================================================================= + +const bool Matcher::match_rule_supported(int opcode) { + if (!has_match_rule(opcode)) { + return false; + } + + switch (opcode) { + case Op_CacheWB: // fall through + case Op_CacheWBPreSync: // fall through + case Op_CacheWBPostSync: + if (!VM_Version::supports_data_cache_line_flush()) { + return false; + } + break; + + case Op_StrCompressedCopy: // fall through + case Op_StrInflatedCopy: // fall through + case Op_CountPositives: + return UseRVV; + + case Op_EncodeISOArray: + return UseRVV && SpecialEncodeISOArray; + + case Op_PopCountI: + case Op_PopCountL: + return UsePopCountInstruction; + + case Op_RotateRight: + case Op_RotateLeft: + case Op_CountLeadingZerosI: + case Op_CountLeadingZerosL: + case Op_CountTrailingZerosI: + case Op_CountTrailingZerosL: + return UseZbb; + } + + return true; // Per default match rules are supported. +} + +// Identify extra cases that we might want to provide match rules for vector nodes and +// other intrinsics guarded with vector length (vlen) and element type (bt). +const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { + if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) { + return false; + } + + return op_vec_supported(opcode); +} + +const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { + return false; +} + +const RegMask* Matcher::predicate_reg_mask(void) { + return NULL; +} + +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { + return NULL; +} + +// Vector calling convention not yet implemented. +const bool Matcher::supports_vector_calling_convention(void) { + return false; +} + +OptoRegPair Matcher::vector_return_value(uint ideal_reg) { + Unimplemented(); + return OptoRegPair(0, 0); +} + +// Is this branch offset short enough that a short branch can be used? +// +// NOTE: If the platform does not provide any short branch variants, then +// this method should return false for offset 0. +// |---label(L1)-----| +// |-----------------| +// |-----------------|----------eq: float------------------- +// |-----------------| // far_cmpD_branch | cmpD_branch +// |------- ---------| feq; | feq; +// |-far_cmpD_branch-| beqz done; | bnez L; +// |-----------------| j L; | +// |-----------------| bind(done); | +// |-----------------|-------------------------------------- +// |-----------------| // so shortBrSize = br_size - 4; +// |-----------------| // so offs = offset - shortBrSize + 4; +// |---label(L2)-----| +bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { + // The passed offset is relative to address of the branch. + int shortBrSize = br_size - 4; + int offs = offset - shortBrSize + 4; + return (-4096 <= offs && offs < 4096); +} + +// Vector width in bytes. +const int Matcher::vector_width_in_bytes(BasicType bt) { + if (UseRVV) { + // The MaxVectorSize should have been set by detecting RVV max vector register size when check UseRVV. + // MaxVectorSize == VM_Version::_initial_vector_length + return MaxVectorSize; + } + return 0; +} + +// Limits on vector size (number of elements) loaded into vector. +const int Matcher::max_vector_size(const BasicType bt) { + return vector_width_in_bytes(bt) / type2aelembytes(bt); +} +const int Matcher::min_vector_size(const BasicType bt) { + return max_vector_size(bt); +} + +// Vector ideal reg. +const uint Matcher::vector_ideal_reg(int len) { + assert(MaxVectorSize >= len, ""); + if (UseRVV) { + return Op_VecA; + } + + ShouldNotReachHere(); + return 0; +} + +const int Matcher::scalable_vector_reg_size(const BasicType bt) { + return Matcher::max_vector_size(bt); +} + +MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +// Return whether or not this register is ever used as an argument. +// This function is used on startup to build the trampoline stubs in +// generateOptoStub. Registers not mentioned will be killed by the VM +// call in the trampoline, and arguments in those registers not be +// available to the callee. +bool Matcher::can_be_java_arg(int reg) +{ + return + reg == R10_num || reg == R10_H_num || + reg == R11_num || reg == R11_H_num || + reg == R12_num || reg == R12_H_num || + reg == R13_num || reg == R13_H_num || + reg == R14_num || reg == R14_H_num || + reg == R15_num || reg == R15_H_num || + reg == R16_num || reg == R16_H_num || + reg == R17_num || reg == R17_H_num || + reg == F10_num || reg == F10_H_num || + reg == F11_num || reg == F11_H_num || + reg == F12_num || reg == F12_H_num || + reg == F13_num || reg == F13_H_num || + reg == F14_num || reg == F14_H_num || + reg == F15_num || reg == F15_H_num || + reg == F16_num || reg == F16_H_num || + reg == F17_num || reg == F17_H_num; +} + +bool Matcher::is_spillable_arg(int reg) +{ + return can_be_java_arg(reg); +} + +uint Matcher::int_pressure_limit() +{ + // A derived pointer is live at CallNode and then is flagged by RA + // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip + // derived pointers and lastly fail to spill after reaching maximum + // number of iterations. Lowering the default pressure threshold to + // (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become + // a high register pressure area of the code so that split_DEF can + // generate DefinitionSpillCopy for the derived pointer. + uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1; + if (!PreserveFramePointer) { + // When PreserveFramePointer is off, frame pointer is allocatable, + // but different from other SOC registers, it is excluded from + // fatproj's mask because its save type is No-Save. Decrease 1 to + // ensure high pressure at fatproj when PreserveFramePointer is off. + // See check_pressure_at_fatproj(). + default_int_pressure_threshold--; + } + return (INTPRESSURE == -1) ? default_int_pressure_threshold : INTPRESSURE; +} + +uint Matcher::float_pressure_limit() +{ + // _FLOAT_REG_mask is generated by adlc from the float_reg register class. + return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE; +} + +bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { + return false; +} + +RegMask Matcher::divI_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for MODI projection of divmodI. +RegMask Matcher::modI_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for DIVL projection of divmodL. +RegMask Matcher::divL_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for MODL projection of divmodL. +RegMask Matcher::modL_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return FP_REG_mask(); +} + +bool size_fits_all_mem_uses(AddPNode* addp, int shift) { + assert_cond(addp != NULL); + for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) { + Node* u = addp->fast_out(i); + if (u != NULL && u->is_Mem()) { + int opsize = u->as_Mem()->memory_size(); + assert(opsize > 0, "unexpected memory operand size"); + if (u->as_Mem()->memory_size() != (1 << shift)) { + return false; + } + } + } + return true; +} + +// Should the Matcher clone input 'm' of node 'n'? +bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { + assert_cond(m != NULL); + if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) + mstack.push(m, Visit); // m = ShiftCntV + return true; + } + return false; +} + +// Should the Matcher clone shifts on addressing modes, expecting them +// to be subsumed into complex addressing expressions or compute them +// into registers? +bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { + return clone_base_plus_offset_address(m, mstack, address_visited); +} + +%} + + + +//----------ENCODING BLOCK----------------------------------------------------- +// This block specifies the encoding classes used by the compiler to +// output byte streams. Encoding classes are parameterized macros +// used by Machine Instruction Nodes in order to generate the bit +// encoding of the instruction. Operands specify their base encoding +// interface with the interface keyword. There are currently +// supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, & +// COND_INTER. REG_INTER causes an operand to generate a function +// which returns its register number when queried. CONST_INTER causes +// an operand to generate a function which returns the value of the +// constant when queried. MEMORY_INTER causes an operand to generate +// four functions which return the Base Register, the Index Register, +// the Scale Value, and the Offset Value of the operand when queried. +// COND_INTER causes an operand to generate six functions which return +// the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional +// instruction. +// +// Instructions specify two basic values for encoding. Again, a +// function is available to check if the constant displacement is an +// oop. They use the ins_encode keyword to specify their encoding +// classes (which must be a sequence of enc_class names, and their +// parameters, specified in the encoding block), and they use the +// opcode keyword to specify, in order, their primary, secondary, and +// tertiary opcode. Only the opcode sections which a particular +// instruction needs for encoding need to be specified. +encode %{ + // BEGIN Non-volatile memory access + + enc_class riscv_enc_li_imm(iRegIorL dst, immIorL src) %{ + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + int64_t con = (int64_t)$src$$constant; + Register dst_reg = as_Register($dst$$reg); + __ li(dst_reg, con); + %} + + enc_class riscv_enc_mov_p(iRegP dst, immP src) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL || con == (address)1) { + ShouldNotReachHere(); + } else { + relocInfo::relocType rtype = $src->constant_reloc(); + if (rtype == relocInfo::oop_type) { + __ movoop(dst_reg, (jobject)con, /*immediate*/true); + } else if (rtype == relocInfo::metadata_type) { + __ mov_metadata(dst_reg, (Metadata*)con); + } else { + assert(rtype == relocInfo::none, "unexpected reloc type"); + __ li(dst_reg, $src$$constant); + } + } + %} + + enc_class riscv_enc_mov_p1(iRegP dst) %{ + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register dst_reg = as_Register($dst$$reg); + __ li(dst_reg, 1); + %} + + enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ + C2_MacroAssembler _masm(&cbuf); + __ load_byte_map_base($dst$$Register); + %} + + enc_class riscv_enc_mov_n(iRegN dst, immN src) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL) { + ShouldNotReachHere(); + } else { + relocInfo::relocType rtype = $src->constant_reloc(); + assert(rtype == relocInfo::oop_type, "unexpected reloc type"); + __ set_narrow_oop(dst_reg, (jobject)con); + } + %} + + enc_class riscv_enc_mov_zero(iRegNorP dst) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + __ mv(dst_reg, zr); + %} + + enc_class riscv_enc_mov_nk(iRegN dst, immNKlass src) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL) { + ShouldNotReachHere(); + } else { + relocInfo::relocType rtype = $src->constant_reloc(); + assert(rtype == relocInfo::metadata_type, "unexpected reloc type"); + __ set_narrow_klass(dst_reg, (Klass *)con); + } + %} + + enc_class riscv_enc_cmpxchgw(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + enc_class riscv_enc_cmpxchgn(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + enc_class riscv_enc_cmpxchg(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + enc_class riscv_enc_cmpxchgw_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + enc_class riscv_enc_cmpxchgn_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + enc_class riscv_enc_cmpxchg_acq(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ + C2_MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + + // compare and branch instruction encodings + + enc_class riscv_enc_j(label lbl) %{ + C2_MacroAssembler _masm(&cbuf); + Label* L = $lbl$$label; + __ j(*L); + %} + + enc_class riscv_enc_far_cmpULtGe_imm0_branch(cmpOpULtGe cmp, iRegIorL op1, label lbl) %{ + C2_MacroAssembler _masm(&cbuf); + Label* L = $lbl$$label; + switch ($cmp$$cmpcode) { + case(BoolTest::ge): + __ j(*L); + break; + case(BoolTest::lt): + break; + default: + Unimplemented(); + } + %} + + // call instruction encodings + + enc_class riscv_enc_partial_subtype_check(iRegP sub, iRegP super, iRegP temp, iRegP result) %{ + Register sub_reg = as_Register($sub$$reg); + Register super_reg = as_Register($super$$reg); + Register temp_reg = as_Register($temp$$reg); + Register result_reg = as_Register($result$$reg); + Register cr_reg = t1; + + Label miss; + Label done; + C2_MacroAssembler _masm(&cbuf); + __ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg, + NULL, &miss); + if ($primary) { + __ mv(result_reg, zr); + } else { + __ mv(cr_reg, zr); + __ j(done); + } + + __ bind(miss); + if (!$primary) { + __ li(cr_reg, 1); + } + + __ bind(done); + %} + + enc_class riscv_enc_java_static_call(method meth) %{ + C2_MacroAssembler _masm(&cbuf); + + address addr = (address)$meth$$method; + address call = NULL; + assert_cond(addr != NULL); + if (!_method) { + // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap. + call = __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + } else { + int method_index = resolved_method_index(cbuf); + RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) + : static_call_Relocation::spec(method_index); + call = __ trampoline_call(Address(addr, rspec), &cbuf); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + + // Emit stub for static call + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + } + %} + + enc_class riscv_enc_java_dynamic_call(method meth) %{ + C2_MacroAssembler _masm(&cbuf); + int method_index = resolved_method_index(cbuf); + address call = __ ic_call((address)$meth$$method, method_index); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + %} + + enc_class riscv_enc_call_epilog() %{ + C2_MacroAssembler _masm(&cbuf); + if (VerifyStackAtCalls) { + // Check that stack depth is unchanged: find majik cookie on stack + __ call_Unimplemented(); + } + %} + + enc_class riscv_enc_java_to_runtime(method meth) %{ + C2_MacroAssembler _masm(&cbuf); + + // some calls to generated routines (arraycopy code) are scheduled + // by C2 as runtime calls. if so we can call them using a jr (they + // will be in a reachable segment) otherwise we have to use a jalr + // which loads the absolute address into a register. + address entry = (address)$meth$$method; + CodeBlob *cb = CodeCache::find_blob(entry); + if (cb != NULL) { + address call = __ trampoline_call(Address(entry, relocInfo::runtime_call_type)); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + } else { + Label retaddr; + __ la(t1, retaddr); + __ la(t0, RuntimeAddress(entry)); + // Leave a breadcrumb for JavaFrameAnchor::capture_last_Java_pc() + __ addi(sp, sp, -2 * wordSize); + __ sd(t1, Address(sp, wordSize)); + __ jalr(t0); + __ bind(retaddr); + __ addi(sp, sp, 2 * wordSize); + } + %} + + // using the cr register as the bool result: 0 for success; others failed. + enc_class riscv_enc_fast_lock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ + C2_MacroAssembler _masm(&cbuf); + Register flag = t1; + Register oop = as_Register($object$$reg); + Register box = as_Register($box$$reg); + Register disp_hdr = as_Register($tmp1$$reg); + Register tmp = as_Register($tmp2$$reg); + Label cont; + Label object_has_monitor; + + assert_different_registers(oop, box, tmp, disp_hdr, t0); + + // Load markWord from object into displaced_header. + __ ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes())); + + if (DiagnoseSyncOnValueBasedClasses != 0) { + __ load_klass(flag, oop); + __ lwu(flag, Address(flag, Klass::access_flags_offset())); + __ andi(flag, flag, JVM_ACC_IS_VALUE_BASED_CLASS, tmp /* tmp */); + __ bnez(flag, cont, true /* is_far */); + } + + // Check for existing monitor + __ andi(t0, disp_hdr, markWord::monitor_value); + __ bnez(t0, object_has_monitor); + + if (!UseHeavyMonitors) { + // Set tmp to be (markWord of object | UNLOCK_VALUE). + __ ori(tmp, disp_hdr, markWord::unlocked_value); + + // Initialize the box. (Must happen before we update the object mark!) + __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); + + // Compare object markWord with an unlocked value (tmp) and if + // equal exchange the stack address of our box with object markWord. + // On failure disp_hdr contains the possibly locked markWord. + __ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq, + Assembler::rl, /*result*/disp_hdr); + __ mv(flag, zr); + __ beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // If the compare-and-exchange succeeded, then we found an unlocked + // object, will have now locked it will continue at label cont + // We did not see an unlocked object so try the fast recursive case. + + // Check if the owner is self by comparing the value in the + // markWord of object (disp_hdr) with the stack pointer. + __ sub(disp_hdr, disp_hdr, sp); + __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markWord::lock_mask_in_place)); + // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, + // hence we can store 0 as the displaced header in the box, which indicates that it is a + // recursive lock. + __ andr(tmp/*==0?*/, disp_hdr, tmp); + __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); + __ mv(flag, tmp); // we can use the value of tmp as the result here + } else { + __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow-path + } + + __ j(cont); + + // Handle existing monitor. + __ bind(object_has_monitor); + // The object's monitor m is unlocked iff m->owner == NULL, + // otherwise m->owner may contain a thread or a stack address. + // + // Try to CAS m->owner from NULL to current thread. + __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markWord::monitor_value)); + __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, + Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) + + // Store a non-null value into the box to avoid looking like a re-entrant + // lock. The fast-path monitor unlock code checks for + // markWord::monitor_value so use markWord::unused_mark which has the + // relevant bit set, and also matches ObjectSynchronizer::slow_enter. + __ mv(tmp, (address)markWord::unused_mark().value()); + __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); + + __ beqz(flag, cont); // CAS success means locking succeeded + + __ bne(flag, xthread, cont); // Check for recursive locking + + // Recursive lock case + __ mv(flag, zr); + __ ld(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); + __ add(tmp, tmp, 1u); + __ sd(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); + + __ bind(cont); + %} + + // using cr flag to indicate the fast_unlock result: 0 for success; others failed. + enc_class riscv_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ + C2_MacroAssembler _masm(&cbuf); + Register flag = t1; + Register oop = as_Register($object$$reg); + Register box = as_Register($box$$reg); + Register disp_hdr = as_Register($tmp1$$reg); + Register tmp = as_Register($tmp2$$reg); + Label cont; + Label object_has_monitor; + + assert_different_registers(oop, box, tmp, disp_hdr, flag); + + if (!UseHeavyMonitors) { + // Find the lock address and load the displaced header from the stack. + __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); + + // If the displaced header is 0, we have a recursive unlock. + __ mv(flag, disp_hdr); + __ beqz(disp_hdr, cont); + } + + // Handle existing monitor. + __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); + __ andi(t0, disp_hdr, markWord::monitor_value); + __ bnez(t0, object_has_monitor); + + if (!UseHeavyMonitors) { + // Check if it is still a light weight lock, this is true if we + // see the stack address of the basicLock in the markWord of the + // object. + + __ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed, + Assembler::rl, /*result*/tmp); + __ xorr(flag, box, tmp); // box == tmp if cas succeeds + } else { + __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow path + } + __ j(cont); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // Handle existing monitor. + __ bind(object_has_monitor); + STATIC_ASSERT(markWord::monitor_value <= INT_MAX); + __ add(tmp, tmp, -(int)markWord::monitor_value); // monitor + __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); + + Label notRecursive; + __ beqz(disp_hdr, notRecursive); // Will be 0 if not recursive. + + // Recursive lock + __ addi(disp_hdr, disp_hdr, -1); + __ sd(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); + __ mv(flag, zr); + __ j(cont); + + __ bind(notRecursive); + __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); + __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); + __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. + __ bnez(flag, cont); + // need a release store here + __ la(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sd(zr, Address(tmp)); // set unowned + + __ bind(cont); + %} + + // arithmetic encodings + + enc_class riscv_enc_divw(iRegI dst, iRegI src1, iRegI src2) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); + __ corrected_idivl(dst_reg, src1_reg, src2_reg, false); + %} + + enc_class riscv_enc_div(iRegI dst, iRegI src1, iRegI src2) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); + __ corrected_idivq(dst_reg, src1_reg, src2_reg, false); + %} + + enc_class riscv_enc_modw(iRegI dst, iRegI src1, iRegI src2) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); + __ corrected_idivl(dst_reg, src1_reg, src2_reg, true); + %} + + enc_class riscv_enc_mod(iRegI dst, iRegI src1, iRegI src2) %{ + C2_MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); + __ corrected_idivq(dst_reg, src1_reg, src2_reg, true); + %} + + enc_class riscv_enc_tail_call(iRegP jump_target) %{ + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register target_reg = as_Register($jump_target$$reg); + __ jr(target_reg); + %} + + enc_class riscv_enc_tail_jmp(iRegP jump_target) %{ + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register target_reg = as_Register($jump_target$$reg); + // exception oop should be in x10 + // ret addr has been popped into ra + // callee expects it in x13 + __ mv(x13, ra); + __ jr(target_reg); + %} + + enc_class riscv_enc_rethrow() %{ + C2_MacroAssembler _masm(&cbuf); + __ far_jump(RuntimeAddress(OptoRuntime::rethrow_stub())); + %} + + enc_class riscv_enc_ret() %{ + C2_MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + __ ret(); + %} + +%} + +//----------FRAME-------------------------------------------------------------- +// Definition of frame structure and management information. +// +// S T A C K L A Y O U T Allocators stack-slot number +// | (to get allocators register number +// G Owned by | | v add OptoReg::stack0()) +// r CALLER | | +// o | +--------+ pad to even-align allocators stack-slot +// w V | pad0 | numbers; owned by CALLER +// t -----------+--------+----> Matcher::_in_arg_limit, unaligned +// h ^ | in | 5 +// | | args | 4 Holes in incoming args owned by SELF +// | | | | 3 +// | | +--------+ +// V | | old out| Empty on Intel, window on Sparc +// | old |preserve| Must be even aligned. +// | SP-+--------+----> Matcher::_old_SP, even aligned +// | | in | 3 area for Intel ret address +// Owned by |preserve| Empty on Sparc. +// SELF +--------+ +// | | pad2 | 2 pad to align old SP +// | +--------+ 1 +// | | locks | 0 +// | +--------+----> OptoReg::stack0(), even aligned +// | | pad1 | 11 pad to align new SP +// | +--------+ +// | | | 10 +// | | spills | 9 spills +// V | | 8 (pad0 slot for callee) +// -----------+--------+----> Matcher::_out_arg_limit, unaligned +// ^ | out | 7 +// | | args | 6 Holes in outgoing args owned by CALLEE +// Owned by +--------+ +// CALLEE | new out| 6 Empty on Intel, window on Sparc +// | new |preserve| Must be even-aligned. +// | SP-+--------+----> Matcher::_new_SP, even aligned +// | | | +// +// Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is +// known from SELF's arguments and the Java calling convention. +// Region 6-7 is determined per call site. +// Note 2: If the calling convention leaves holes in the incoming argument +// area, those holes are owned by SELF. Holes in the outgoing area +// are owned by the CALLEE. Holes should not be nessecary in the +// incoming area, as the Java calling convention is completely under +// the control of the AD file. Doubles can be sorted and packed to +// avoid holes. Holes in the outgoing arguments may be nessecary for +// varargs C calling conventions. +// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is +// even aligned with pad0 as needed. +// Region 6 is even aligned. Region 6-7 is NOT even aligned; +// (the latter is true on Intel but is it false on RISCV?) +// region 6-11 is even aligned; it may be padded out more so that +// the region from SP to FP meets the minimum stack alignment. +// Note 4: For I2C adapters, the incoming FP may not meet the minimum stack +// alignment. Region 11, pad1, may be dynamically extended so that +// SP meets the minimum alignment. + +frame %{ + // These three registers define part of the calling convention + // between compiled code and the interpreter. + + // Inline Cache Register or methodOop for I2C. + inline_cache_reg(R31); + + // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] + cisc_spilling_operand_name(indOffset); + + // Number of stack slots consumed by locking an object + // generate Compile::sync_stack_slots + // VMRegImpl::slots_per_word = wordSize / stack_slot_size = 8 / 4 = 2 + sync_stack_slots(1 * VMRegImpl::slots_per_word); + + // Compiled code's Frame Pointer + frame_pointer(R2); + + // Interpreter stores its frame pointer in a register which is + // stored to the stack by I2CAdaptors. + // I2CAdaptors convert from interpreted java to compiled java. + interpreter_frame_pointer(R8); + + // Stack alignment requirement + stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) + + // Number of outgoing stack slots killed above the out_preserve_stack_slots + // for calls to C. Supports the var-args backing area for register parms. + varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes / BytesPerInt); + + // The after-PROLOG location of the return address. Location of + // return address specifies a type (REG or STACK) and a number + // representing the register number (i.e. - use a register name) or + // stack slot. + // Ret Addr is on stack in slot 0 if no locks or verification or alignment. + // Otherwise, it is above the locks and verification slot and alignment word + // TODO this may well be correct but need to check why that - 2 is there + // ppc port uses 0 but we definitely need to allow for fixed_slots + // which folds in the space used for monitors + return_addr(STACK - 2 + + align_up((Compile::current()->in_preserve_stack_slots() + + Compile::current()->fixed_slots()), + stack_alignment_in_slots())); + + // Location of compiled Java return values. Same as C for now. + return_value + %{ + assert(ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, + "only return normal values"); + + static const int lo[Op_RegL + 1] = { // enum name + 0, // Op_Node + 0, // Op_Set + R10_num, // Op_RegN + R10_num, // Op_RegI + R10_num, // Op_RegP + F10_num, // Op_RegF + F10_num, // Op_RegD + R10_num // Op_RegL + }; + + static const int hi[Op_RegL + 1] = { // enum name + 0, // Op_Node + 0, // Op_Set + OptoReg::Bad, // Op_RegN + OptoReg::Bad, // Op_RegI + R10_H_num, // Op_RegP + OptoReg::Bad, // Op_RegF + F10_H_num, // Op_RegD + R10_H_num // Op_RegL + }; + + return OptoRegPair(hi[ideal_reg], lo[ideal_reg]); + %} +%} + +//----------ATTRIBUTES--------------------------------------------------------- +//----------Operand Attributes------------------------------------------------- +op_attrib op_cost(1); // Required cost attribute + +//----------Instruction Attributes--------------------------------------------- +ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute +ins_attrib ins_size(32); // Required size attribute (in bits) +ins_attrib ins_short_branch(0); // Required flag: is this instruction + // a non-matching short branch variant + // of some long branch? +ins_attrib ins_alignment(4); // Required alignment attribute (must + // be a power of 2) specifies the + // alignment that some part of the + // instruction (not necessarily the + // start) requires. If > 1, a + // compute_padding() function must be + // provided for the instruction + +//----------OPERANDS----------------------------------------------------------- +// Operand definitions must precede instruction definitions for correct parsing +// in the ADLC because operands constitute user defined types which are used in +// instruction definitions. + +//----------Simple Operands---------------------------------------------------- + +// Integer operands 32 bit +// 32 bit immediate +operand immI() +%{ + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 32 bit zero +operand immI0() +%{ + predicate(n->get_int() == 0); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 32 bit unit increment +operand immI_1() +%{ + predicate(n->get_int() == 1); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 32 bit unit decrement +operand immI_M1() +%{ + predicate(n->get_int() == -1); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 6-bit int, greater than 32 +operand uimmI6_ge32() %{ + predicate(((unsigned int)(n->get_int()) < 64) && (n->get_int() >= 32)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immI_le_4() +%{ + predicate(n->get_int() <= 4); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immI_16() +%{ + predicate(n->get_int() == 16); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immI_24() +%{ + predicate(n->get_int() == 24); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immI_31() +%{ + predicate(n->get_int() == 31); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immI_63() +%{ + predicate(n->get_int() == 63); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 32 bit integer valid for add immediate +operand immIAdd() +%{ + predicate(Assembler::operand_valid_for_add_immediate((int64_t)n->get_int())); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 32 bit integer valid for sub immediate +operand immISub() +%{ + predicate(Assembler::operand_valid_for_add_immediate(-(int64_t)n->get_int())); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 5 bit signed value. +operand immI5() +%{ + predicate(n->get_int() <= 15 && n->get_int() >= -16); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 5 bit signed value (simm5) +operand immL5() +%{ + predicate(n->get_long() <= 15 && n->get_long() >= -16); + match(ConL); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Integer operands 64 bit +// 64 bit immediate +operand immL() +%{ + match(ConL); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 64 bit zero +operand immL0() +%{ + predicate(n->get_long() == 0); + match(ConL); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Pointer operands +// Pointer Immediate +operand immP() +%{ + match(ConP); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// NULL Pointer Immediate +operand immP0() +%{ + predicate(n->get_ptr() == 0); + match(ConP); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Pointer Immediate One +// this is used in object initialization (initial object header) +operand immP_1() +%{ + predicate(n->get_ptr() == 1); + match(ConP); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Card Table Byte Map Base +operand immByteMapBase() +%{ + // Get base of card map + predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && + (CardTable::CardValue*)n->get_ptr() == + ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); + match(ConP); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Int Immediate: low 16-bit mask +operand immI_16bits() +%{ + predicate(n->get_int() == 0xFFFF); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: low 32-bit mask +operand immL_32bits() +%{ + predicate(n->get_long() == 0xFFFFFFFFL); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 64 bit unit decrement +operand immL_M1() +%{ + predicate(n->get_long() == -1); + match(ConL); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + + +// 32 bit offset of pc in thread anchor + +operand immL_pc_off() +%{ + predicate(n->get_long() == in_bytes(JavaThread::frame_anchor_offset()) + + in_bytes(JavaFrameAnchor::last_Java_pc_offset())); + match(ConL); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 64 bit integer valid for add immediate +operand immLAdd() +%{ + predicate(Assembler::operand_valid_for_add_immediate(n->get_long())); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// 64 bit integer valid for sub immediate +operand immLSub() +%{ + predicate(Assembler::operand_valid_for_add_immediate(-(n->get_long()))); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Narrow pointer operands +// Narrow Pointer Immediate +operand immN() +%{ + match(ConN); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Narrow NULL Pointer Immediate +operand immN0() +%{ + predicate(n->get_narrowcon() == 0); + match(ConN); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immNKlass() +%{ + match(ConNKlass); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Float and Double operands +// Double Immediate +operand immD() +%{ + match(ConD); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Double Immediate: +0.0d +operand immD0() +%{ + predicate(jlong_cast(n->getd()) == 0); + match(ConD); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Float Immediate +operand immF() +%{ + match(ConF); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Float Immediate: +0.0f. +operand immF0() +%{ + predicate(jint_cast(n->getf()) == 0); + match(ConF); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immIOffset() +%{ + predicate(is_imm_in_range(n->get_int(), 12, 0)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immLOffset() +%{ + predicate(is_imm_in_range(n->get_long(), 12, 0)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Scale values +operand immIScale() +%{ + predicate(1 <= n->get_int() && (n->get_int() <= 3)); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Integer 32 bit Register Operands +operand iRegI() +%{ + constraint(ALLOC_IN_RC(any_reg32)); + match(RegI); + match(iRegINoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Integer 32 bit Register not Special +operand iRegINoSp() +%{ + constraint(ALLOC_IN_RC(no_special_reg32)); + match(RegI); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Register R10 only +operand iRegI_R10() +%{ + constraint(ALLOC_IN_RC(int_r10_reg)); + match(RegI); + match(iRegINoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Register R12 only +operand iRegI_R12() +%{ + constraint(ALLOC_IN_RC(int_r12_reg)); + match(RegI); + match(iRegINoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Register R13 only +operand iRegI_R13() +%{ + constraint(ALLOC_IN_RC(int_r13_reg)); + match(RegI); + match(iRegINoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Register R14 only +operand iRegI_R14() +%{ + constraint(ALLOC_IN_RC(int_r14_reg)); + match(RegI); + match(iRegINoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Integer 64 bit Register Operands +operand iRegL() +%{ + constraint(ALLOC_IN_RC(any_reg)); + match(RegL); + match(iRegLNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Integer 64 bit Register not Special +operand iRegLNoSp() +%{ + constraint(ALLOC_IN_RC(no_special_reg)); + match(RegL); + match(iRegL_R10); + format %{ %} + interface(REG_INTER); +%} + +// Long 64 bit Register R28 only +operand iRegL_R28() +%{ + constraint(ALLOC_IN_RC(r28_reg)); + match(RegL); + match(iRegLNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Long 64 bit Register R29 only +operand iRegL_R29() +%{ + constraint(ALLOC_IN_RC(r29_reg)); + match(RegL); + match(iRegLNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Long 64 bit Register R30 only +operand iRegL_R30() +%{ + constraint(ALLOC_IN_RC(r30_reg)); + match(RegL); + match(iRegLNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer Register Operands +// Pointer Register +operand iRegP() +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(RegP); + match(iRegPNoSp); + match(iRegP_R10); + match(javaThread_RegP); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer 64 bit Register not Special +operand iRegPNoSp() +%{ + constraint(ALLOC_IN_RC(no_special_ptr_reg)); + match(RegP); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand iRegP_R10() +%{ + constraint(ALLOC_IN_RC(r10_reg)); + match(RegP); + // match(iRegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer 64 bit Register R11 only +operand iRegP_R11() +%{ + constraint(ALLOC_IN_RC(r11_reg)); + match(RegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand iRegP_R12() +%{ + constraint(ALLOC_IN_RC(r12_reg)); + match(RegP); + // match(iRegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer 64 bit Register R13 only +operand iRegP_R13() +%{ + constraint(ALLOC_IN_RC(r13_reg)); + match(RegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand iRegP_R14() +%{ + constraint(ALLOC_IN_RC(r14_reg)); + match(RegP); + // match(iRegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand iRegP_R15() +%{ + constraint(ALLOC_IN_RC(r15_reg)); + match(RegP); + // match(iRegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand iRegP_R16() +%{ + constraint(ALLOC_IN_RC(r16_reg)); + match(RegP); + // match(iRegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer 64 bit Register R28 only +operand iRegP_R28() +%{ + constraint(ALLOC_IN_RC(r28_reg)); + match(RegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Pointer Register Operands +// Narrow Pointer Register +operand iRegN() +%{ + constraint(ALLOC_IN_RC(any_reg32)); + match(RegN); + match(iRegNNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Integer 64 bit Register not Special +operand iRegNNoSp() +%{ + constraint(ALLOC_IN_RC(no_special_reg32)); + match(RegN); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// heap base register -- used for encoding immN0 +operand iRegIHeapbase() +%{ + constraint(ALLOC_IN_RC(heapbase_reg)); + match(RegI); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Long 64 bit Register R10 only +operand iRegL_R10() +%{ + constraint(ALLOC_IN_RC(r10_reg)); + match(RegL); + match(iRegLNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Float Register +// Float register operands +operand fRegF() +%{ + constraint(ALLOC_IN_RC(float_reg)); + match(RegF); + + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Double Register +// Double register operands +operand fRegD() +%{ + constraint(ALLOC_IN_RC(double_reg)); + match(RegD); + + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Generic vector class. This will be used for +// all vector operands. +operand vReg() +%{ + constraint(ALLOC_IN_RC(vectora_reg)); + match(VecA); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vReg_V1() +%{ + constraint(ALLOC_IN_RC(v1_reg)); + match(VecA); + match(vReg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vReg_V2() +%{ + constraint(ALLOC_IN_RC(v2_reg)); + match(VecA); + match(vReg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vReg_V3() +%{ + constraint(ALLOC_IN_RC(v3_reg)); + match(VecA); + match(vReg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vReg_V4() +%{ + constraint(ALLOC_IN_RC(v4_reg)); + match(VecA); + match(vReg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vReg_V5() +%{ + constraint(ALLOC_IN_RC(v5_reg)); + match(VecA); + match(vReg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +// Java Thread Register +operand javaThread_RegP(iRegP reg) +%{ + constraint(ALLOC_IN_RC(java_thread_reg)); // java_thread_reg + match(reg); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +//----------Memory Operands---------------------------------------------------- +// RISCV has only base_plus_offset and literal address mode, so no need to use +// index and scale. Here set index as 0xffffffff and scale as 0x0. +operand indirect(iRegP reg) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(reg); + op_cost(0); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp(0x0); + %} +%} + +operand indOffI(iRegP reg, immIOffset off) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP reg off); + op_cost(0); + format %{ "[$reg, $off]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp($off); + %} +%} + +operand indOffL(iRegP reg, immLOffset off) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP reg off); + op_cost(0); + format %{ "[$reg, $off]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp($off); + %} +%} + +operand indirectN(iRegN reg) +%{ + predicate(CompressedOops::shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(DecodeN reg); + op_cost(0); + format %{ "[$reg]\t# narrow" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp(0x0); + %} +%} + +operand indOffIN(iRegN reg, immIOffset off) +%{ + predicate(CompressedOops::shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + op_cost(0); + format %{ "[$reg, $off]\t# narrow" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp($off); + %} +%} + +operand indOffLN(iRegN reg, immLOffset off) +%{ + predicate(CompressedOops::shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + op_cost(0); + format %{ "[$reg, $off]\t# narrow" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp($off); + %} +%} + +// RISCV opto stubs need to write to the pc slot in the thread anchor +operand thread_anchor_pc(javaThread_RegP reg, immL_pc_off off) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP reg off); + op_cost(0); + format %{ "[$reg, $off]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0xffffffff); + scale(0x0); + disp($off); + %} +%} + + +//----------Special Memory Operands-------------------------------------------- +// Stack Slot Operand - This operand is used for loading and storing temporary +// values on the stack where a match requires a value to +// flow through memory. +operand stackSlotI(sRegI reg) +%{ + constraint(ALLOC_IN_RC(stack_slots)); + // No match rule because this operand is only generated in matching + // match(RegI); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base(0x02); // RSP + index(0xffffffff); // No Index + scale(0x0); // No Scale + disp($reg); // Stack Offset + %} +%} + +operand stackSlotF(sRegF reg) +%{ + constraint(ALLOC_IN_RC(stack_slots)); + // No match rule because this operand is only generated in matching + // match(RegF); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base(0x02); // RSP + index(0xffffffff); // No Index + scale(0x0); // No Scale + disp($reg); // Stack Offset + %} +%} + +operand stackSlotD(sRegD reg) +%{ + constraint(ALLOC_IN_RC(stack_slots)); + // No match rule because this operand is only generated in matching + // match(RegD); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base(0x02); // RSP + index(0xffffffff); // No Index + scale(0x0); // No Scale + disp($reg); // Stack Offset + %} +%} + +operand stackSlotL(sRegL reg) +%{ + constraint(ALLOC_IN_RC(stack_slots)); + // No match rule because this operand is only generated in matching + // match(RegL); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base(0x02); // RSP + index(0xffffffff); // No Index + scale(0x0); // No Scale + disp($reg); // Stack Offset + %} +%} + +// Special operand allowing long args to int ops to be truncated for free + +operand iRegL2I(iRegL reg) %{ + + op_cost(0); + + match(ConvL2I reg); + + format %{ "l2i($reg)" %} + + interface(REG_INTER) +%} + + +// Comparison Operands +// NOTE: Label is a predefined operand which should not be redefined in +// the AD file. It is generically handled within the ADLC. + +//----------Conditional Branch Operands---------------------------------------- +// Comparison Op - This is the operation of the comparison, and is limited to +// the following set of codes: +// L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) +// +// Other attributes of the comparison, such as unsignedness, are specified +// by the comparison instruction that sets a condition code flags register. +// That result is represented by a flags operand whose subtype is appropriate +// to the unsignedness (etc.) of the comparison. +// +// Later, the instruction which matches both the Comparison Op (a Bool) and +// the flags (produced by the Cmp) specifies the coding of the comparison op +// by matching a specific subtype of Bool operand below, such as cmpOpU. + + +// used for signed integral comparisons and fp comparisons +operand cmpOp() +%{ + match(Bool); + + format %{ "" %} + + // the values in interface derives from struct BoolTest::mask + interface(COND_INTER) %{ + equal(0x0, "eq"); + greater(0x1, "gt"); + overflow(0x2, "overflow"); + less(0x3, "lt"); + not_equal(0x4, "ne"); + less_equal(0x5, "le"); + no_overflow(0x6, "no_overflow"); + greater_equal(0x7, "ge"); + %} +%} + +// used for unsigned integral comparisons +operand cmpOpU() +%{ + match(Bool); + + format %{ "" %} + // the values in interface derives from struct BoolTest::mask + interface(COND_INTER) %{ + equal(0x0, "eq"); + greater(0x1, "gtu"); + overflow(0x2, "overflow"); + less(0x3, "ltu"); + not_equal(0x4, "ne"); + less_equal(0x5, "leu"); + no_overflow(0x6, "no_overflow"); + greater_equal(0x7, "geu"); + %} +%} + +// used for certain integral comparisons which can be +// converted to bxx instructions +operand cmpOpEqNe() +%{ + match(Bool); + op_cost(0); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq); + + format %{ "" %} + interface(COND_INTER) %{ + equal(0x0, "eq"); + greater(0x1, "gt"); + overflow(0x2, "overflow"); + less(0x3, "lt"); + not_equal(0x4, "ne"); + less_equal(0x5, "le"); + no_overflow(0x6, "no_overflow"); + greater_equal(0x7, "ge"); + %} +%} + +operand cmpOpULtGe() +%{ + match(Bool); + op_cost(0); + predicate(n->as_Bool()->_test._test == BoolTest::lt || + n->as_Bool()->_test._test == BoolTest::ge); + + format %{ "" %} + interface(COND_INTER) %{ + equal(0x0, "eq"); + greater(0x1, "gt"); + overflow(0x2, "overflow"); + less(0x3, "lt"); + not_equal(0x4, "ne"); + less_equal(0x5, "le"); + no_overflow(0x6, "no_overflow"); + greater_equal(0x7, "ge"); + %} +%} + +operand cmpOpUEqNeLeGt() +%{ + match(Bool); + op_cost(0); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); + + format %{ "" %} + interface(COND_INTER) %{ + equal(0x0, "eq"); + greater(0x1, "gt"); + overflow(0x2, "overflow"); + less(0x3, "lt"); + not_equal(0x4, "ne"); + less_equal(0x5, "le"); + no_overflow(0x6, "no_overflow"); + greater_equal(0x7, "ge"); + %} +%} + + +// Flags register, used as output of compare logic +operand rFlagsReg() +%{ + constraint(ALLOC_IN_RC(reg_flags)); + match(RegFlags); + + op_cost(0); + format %{ "RFLAGS" %} + interface(REG_INTER); +%} + +// Special Registers + +// Method Register +operand inline_cache_RegP(iRegP reg) +%{ + constraint(ALLOC_IN_RC(method_reg)); // inline_cache_reg + match(reg); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +//----------OPERAND CLASSES---------------------------------------------------- +// Operand Classes are groups of operands that are used as to simplify +// instruction definitions by not requiring the AD writer to specify +// separate instructions for every form of operand when the +// instruction accepts multiple operand types with the same basic +// encoding and format. The classic case of this is memory operands. + +// memory is used to define read/write location for load/store +// instruction defs. we can turn a memory op into an Address + +opclass memory(indirect, indOffI, indOffL, indirectN, indOffIN, indOffLN); + +// iRegIorL2I is used for src inputs in rules for 32 bit int (I) +// operations. it allows the src to be either an iRegI or a (ConvL2I +// iRegL). in the latter case the l2i normally planted for a ConvL2I +// can be elided because the 32-bit instruction will just employ the +// lower 32 bits anyway. +// +// n.b. this does not elide all L2I conversions. if the truncated +// value is consumed by more than one operation then the ConvL2I +// cannot be bundled into the consuming nodes so an l2i gets planted +// (actually a mvw $dst $src) and the downstream instructions consume +// the result of the l2i as an iRegI input. That's a shame since the +// mvw is actually redundant but its not too costly. + +opclass iRegIorL2I(iRegI, iRegL2I); +opclass iRegIorL(iRegI, iRegL); +opclass iRegNorP(iRegN, iRegP); +opclass iRegILNP(iRegI, iRegL, iRegN, iRegP); +opclass iRegILNPNoSp(iRegINoSp, iRegLNoSp, iRegNNoSp, iRegPNoSp); +opclass immIorL(immI, immL); + +//----------PIPELINE----------------------------------------------------------- +// Rules which define the behavior of the target architectures pipeline. + +// For specific pipelines, e.g. generic RISC-V, define the stages of that pipeline +//pipe_desc(ID, EX, MEM, WR); +#define ID S0 +#define EX S1 +#define MEM S2 +#define WR S3 + +// Integer ALU reg operation +pipeline %{ + +attributes %{ + // RISC-V instructions are of fixed length + fixed_size_instructions; // Fixed size instructions TODO does + max_instructions_per_bundle = 2; // Generic RISC-V 1, Sifive Series 7 2 + // RISC-V instructions come in 32-bit word units + instruction_unit_size = 4; // An instruction is 4 bytes long + instruction_fetch_unit_size = 64; // The processor fetches one line + instruction_fetch_units = 1; // of 64 bytes + + // List of nop instructions + nops( MachNop ); +%} + +// We don't use an actual pipeline model so don't care about resources +// or description. we do use pipeline classes to introduce fixed +// latencies + +//----------RESOURCES---------------------------------------------------------- +// Resources are the functional units available to the machine + +// Generic RISC-V pipeline +// 1 decoder +// 1 instruction decoded per cycle +// 1 load/store ops per cycle, 1 branch, 1 FPU +// 1 mul, 1 div + +resources ( DECODE, + ALU, + MUL, + DIV, + BRANCH, + LDST, + FPU); + +//----------PIPELINE DESCRIPTION----------------------------------------------- +// Pipeline Description specifies the stages in the machine's pipeline + +// Define the pipeline as a generic 6 stage pipeline +pipe_desc(S0, S1, S2, S3, S4, S5); + +//----------PIPELINE CLASSES--------------------------------------------------- +// Pipeline Classes describe the stages in which input and output are +// referenced by the hardware pipeline. + +pipe_class fp_dop_reg_reg_s(fRegF dst, fRegF src1, fRegF src2) +%{ + single_instruction; + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_dop_reg_reg_d(fRegD dst, fRegD src1, fRegD src2) +%{ + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_uop_s(fRegF dst, fRegF src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_uop_d(fRegD dst, fRegD src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_d2f(fRegF dst, fRegD src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_f2d(fRegD dst, fRegF src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_f2i(iRegINoSp dst, fRegF src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_f2l(iRegLNoSp dst, fRegF src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_i2f(fRegF dst, iRegIorL2I src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_l2f(fRegF dst, iRegL src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_d2i(iRegINoSp dst, fRegD src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_d2l(iRegLNoSp dst, fRegD src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_i2d(fRegD dst, iRegIorL2I src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_l2d(fRegD dst, iRegIorL2I src) +%{ + single_instruction; + src : S1(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_div_s(fRegF dst, fRegF src1, fRegF src2) +%{ + single_instruction; + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_div_d(fRegD dst, fRegD src1, fRegD src2) +%{ + single_instruction; + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_sqrt_s(fRegF dst, fRegF src1, fRegF src2) +%{ + single_instruction; + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_sqrt_d(fRegD dst, fRegD src1, fRegD src2) +%{ + single_instruction; + src1 : S1(read); + src2 : S2(read); + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_load_constant_s(fRegF dst) +%{ + single_instruction; + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_load_constant_d(fRegD dst) +%{ + single_instruction; + dst : S5(write); + DECODE : ID; + FPU : S5; +%} + +pipe_class fp_load_mem_s(fRegF dst, memory mem) +%{ + single_instruction; + mem : S1(read); + dst : S5(write); + DECODE : ID; + LDST : MEM; +%} + +pipe_class fp_load_mem_d(fRegD dst, memory mem) +%{ + single_instruction; + mem : S1(read); + dst : S5(write); + DECODE : ID; + LDST : MEM; +%} + +pipe_class fp_store_reg_s(fRegF src, memory mem) +%{ + single_instruction; + src : S1(read); + mem : S5(write); + DECODE : ID; + LDST : MEM; +%} + +pipe_class fp_store_reg_d(fRegD src, memory mem) +%{ + single_instruction; + src : S1(read); + mem : S5(write); + DECODE : ID; + LDST : MEM; +%} + +//------- Integer ALU operations -------------------------- + +// Integer ALU reg-reg operation +// Operands needs in ID, result generated in EX +// E.g. ADD Rd, Rs1, Rs2 +pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + dst : EX(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + ALU : EX; +%} + +// Integer ALU reg operation with constant shift +// E.g. SLLI Rd, Rs1, #shift +pipe_class ialu_reg_shift(iRegI dst, iRegI src1) +%{ + single_instruction; + dst : EX(write); + src1 : ID(read); + DECODE : ID; + ALU : EX; +%} + +// Integer ALU reg-reg operation with variable shift +// both operands must be available in ID +// E.g. SLL Rd, Rs1, Rs2 +pipe_class ialu_reg_reg_vshift(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + dst : EX(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + ALU : EX; +%} + +// Integer ALU reg operation +// E.g. NEG Rd, Rs2 +pipe_class ialu_reg(iRegI dst, iRegI src) +%{ + single_instruction; + dst : EX(write); + src : ID(read); + DECODE : ID; + ALU : EX; +%} + +// Integer ALU reg immediate operation +// E.g. ADDI Rd, Rs1, #imm +pipe_class ialu_reg_imm(iRegI dst, iRegI src1) +%{ + single_instruction; + dst : EX(write); + src1 : ID(read); + DECODE : ID; + ALU : EX; +%} + +// Integer ALU immediate operation (no source operands) +// E.g. LI Rd, #imm +pipe_class ialu_imm(iRegI dst) +%{ + single_instruction; + dst : EX(write); + DECODE : ID; + ALU : EX; +%} + +//------- Multiply pipeline operations -------------------- + +// Multiply reg-reg +// E.g. MULW Rd, Rs1, Rs2 +pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + dst : WR(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + MUL : WR; +%} + +// E.g. MUL RD, Rs1, Rs2 +pipe_class lmul_reg_reg(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + fixed_latency(3); // Maximum latency for 64 bit mul + dst : WR(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + MUL : WR; +%} + +//------- Divide pipeline operations -------------------- + +// E.g. DIVW Rd, Rs1, Rs2 +pipe_class idiv_reg_reg(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + fixed_latency(8); // Maximum latency for 32 bit divide + dst : WR(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + DIV : WR; +%} + +// E.g. DIV RD, Rs1, Rs2 +pipe_class ldiv_reg_reg(iRegI dst, iRegI src1, iRegI src2) +%{ + single_instruction; + fixed_latency(16); // Maximum latency for 64 bit divide + dst : WR(write); + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + DIV : WR; +%} + +//------- Load pipeline operations ------------------------ + +// Load - reg, mem +// E.g. LA Rd, mem +pipe_class iload_reg_mem(iRegI dst, memory mem) +%{ + single_instruction; + dst : WR(write); + mem : ID(read); + DECODE : ID; + LDST : MEM; +%} + +// Load - reg, reg +// E.g. LD Rd, Rs +pipe_class iload_reg_reg(iRegI dst, iRegI src) +%{ + single_instruction; + dst : WR(write); + src : ID(read); + DECODE : ID; + LDST : MEM; +%} + +//------- Store pipeline operations ----------------------- + +// Store - zr, mem +// E.g. SD zr, mem +pipe_class istore_mem(memory mem) +%{ + single_instruction; + mem : ID(read); + DECODE : ID; + LDST : MEM; +%} + +// Store - reg, mem +// E.g. SD Rs, mem +pipe_class istore_reg_mem(iRegI src, memory mem) +%{ + single_instruction; + mem : ID(read); + src : EX(read); + DECODE : ID; + LDST : MEM; +%} + +// Store - reg, reg +// E.g. SD Rs2, Rs1 +pipe_class istore_reg_reg(iRegI dst, iRegI src) +%{ + single_instruction; + dst : ID(read); + src : EX(read); + DECODE : ID; + LDST : MEM; +%} + +//------- Store pipeline operations ----------------------- + +// Branch +pipe_class pipe_branch() +%{ + single_instruction; + DECODE : ID; + BRANCH : EX; +%} + +// Branch +pipe_class pipe_branch_reg(iRegI src) +%{ + single_instruction; + src : ID(read); + DECODE : ID; + BRANCH : EX; +%} + +// Compare & Branch +// E.g. BEQ Rs1, Rs2, L +pipe_class pipe_cmp_branch(iRegI src1, iRegI src2) +%{ + single_instruction; + src1 : ID(read); + src2 : ID(read); + DECODE : ID; + BRANCH : EX; +%} + +// E.g. BEQZ Rs, L +pipe_class pipe_cmpz_branch(iRegI src) +%{ + single_instruction; + src : ID(read); + DECODE : ID; + BRANCH : EX; +%} + +//------- Synchronisation operations ---------------------- +// Any operation requiring serialization +// E.g. FENCE/Atomic Ops/Load Acquire/Store Release +pipe_class pipe_serial() +%{ + single_instruction; + force_serialization; + fixed_latency(16); + DECODE : ID; + LDST : MEM; +%} + +pipe_class pipe_slow() +%{ + instruction_count(10); + multiple_bundles; + force_serialization; + fixed_latency(16); + DECODE : ID; + LDST : MEM; +%} + +// Empty pipeline class +pipe_class pipe_class_empty() +%{ + single_instruction; + fixed_latency(0); +%} + +// Default pipeline class. +pipe_class pipe_class_default() +%{ + single_instruction; + fixed_latency(2); +%} + +// Pipeline class for compares. +pipe_class pipe_class_compare() +%{ + single_instruction; + fixed_latency(16); +%} + +// Pipeline class for memory operations. +pipe_class pipe_class_memory() +%{ + single_instruction; + fixed_latency(16); +%} + +// Pipeline class for call. +pipe_class pipe_class_call() +%{ + single_instruction; + fixed_latency(100); +%} + +// Define the class for the Nop node. +define %{ + MachNop = pipe_class_empty; +%} +%} +//----------INSTRUCTIONS------------------------------------------------------- +// +// match -- States which machine-independent subtree may be replaced +// by this instruction. +// ins_cost -- The estimated cost of this instruction is used by instruction +// selection to identify a minimum cost tree of machine +// instructions that matches a tree of machine-independent +// instructions. +// format -- A string providing the disassembly for this instruction. +// The value of an instruction's operand may be inserted +// by referring to it with a '$' prefix. +// opcode -- Three instruction opcodes may be provided. These are referred +// to within an encode class as $primary, $secondary, and $tertiary +// rrspectively. The primary opcode is commonly used to +// indicate the type of machine instruction, while secondary +// and tertiary are often used for prefix options or addressing +// modes. +// ins_encode -- A list of encode classes with parameters. The encode class +// name must have been defined in an 'enc_class' specification +// in the encode section of the architecture description. + +// ============================================================================ +// Memory (Load/Store) Instructions + +// Load Instructions + +// Load Byte (8 bit signed) +instruct loadB(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadB mem)); + + ins_cost(LOAD_COST); + format %{ "lb $dst, $mem\t# byte, #@loadB" %} + + ins_encode %{ + __ lb(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Byte (8 bit signed) into long +instruct loadB2L(iRegLNoSp dst, memory mem) +%{ + match(Set dst (ConvI2L (LoadB mem))); + + ins_cost(LOAD_COST); + format %{ "lb $dst, $mem\t# byte, #@loadB2L" %} + + ins_encode %{ + __ lb(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Byte (8 bit unsigned) +instruct loadUB(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadUB mem)); + + ins_cost(LOAD_COST); + format %{ "lbu $dst, $mem\t# byte, #@loadUB" %} + + ins_encode %{ + __ lbu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Byte (8 bit unsigned) into long +instruct loadUB2L(iRegLNoSp dst, memory mem) +%{ + match(Set dst (ConvI2L (LoadUB mem))); + + ins_cost(LOAD_COST); + format %{ "lbu $dst, $mem\t# byte, #@loadUB2L" %} + + ins_encode %{ + __ lbu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Short (16 bit signed) +instruct loadS(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadS mem)); + + ins_cost(LOAD_COST); + format %{ "lh $dst, $mem\t# short, #@loadS" %} + + ins_encode %{ + __ lh(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Short (16 bit signed) into long +instruct loadS2L(iRegLNoSp dst, memory mem) +%{ + match(Set dst (ConvI2L (LoadS mem))); + + ins_cost(LOAD_COST); + format %{ "lh $dst, $mem\t# short, #@loadS2L" %} + + ins_encode %{ + __ lh(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Char (16 bit unsigned) +instruct loadUS(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadUS mem)); + + ins_cost(LOAD_COST); + format %{ "lhu $dst, $mem\t# short, #@loadUS" %} + + ins_encode %{ + __ lhu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Short/Char (16 bit unsigned) into long +instruct loadUS2L(iRegLNoSp dst, memory mem) +%{ + match(Set dst (ConvI2L (LoadUS mem))); + + ins_cost(LOAD_COST); + format %{ "lhu $dst, $mem\t# short, #@loadUS2L" %} + + ins_encode %{ + __ lhu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Integer (32 bit signed) +instruct loadI(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadI mem)); + + ins_cost(LOAD_COST); + format %{ "lw $dst, $mem\t# int, #@loadI" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ lw(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Integer (32 bit signed) into long +instruct loadI2L(iRegLNoSp dst, memory mem) +%{ + match(Set dst (ConvI2L (LoadI mem))); + + ins_cost(LOAD_COST); + format %{ "lw $dst, $mem\t# int, #@loadI2L" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ lw(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Integer (32 bit unsigned) into long +instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask) +%{ + match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); + + ins_cost(LOAD_COST); + format %{ "lwu $dst, $mem\t# int, #@loadUI2L" %} + + ins_encode %{ + __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Long (64 bit signed) +instruct loadL(iRegLNoSp dst, memory mem) +%{ + match(Set dst (LoadL mem)); + + ins_cost(LOAD_COST); + format %{ "ld $dst, $mem\t# int, #@loadL" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Range +instruct loadRange(iRegINoSp dst, memory mem) +%{ + match(Set dst (LoadRange mem)); + + ins_cost(LOAD_COST); + format %{ "lwu $dst, $mem\t# range, #@loadRange" %} + + ins_encode %{ + __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Pointer +instruct loadP(iRegPNoSp dst, memory mem) +%{ + match(Set dst (LoadP mem)); + predicate(n->as_Load()->barrier_data() == 0); + + ins_cost(LOAD_COST); + format %{ "ld $dst, $mem\t# ptr, #@loadP" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Compressed Pointer +instruct loadN(iRegNNoSp dst, memory mem) +%{ + match(Set dst (LoadN mem)); + + ins_cost(LOAD_COST); + format %{ "lwu $dst, $mem\t# loadN, compressed ptr, #@loadN" %} + + ins_encode %{ + __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Klass Pointer +instruct loadKlass(iRegPNoSp dst, memory mem) +%{ + match(Set dst (LoadKlass mem)); + + ins_cost(LOAD_COST); + format %{ "ld $dst, $mem\t# class, #@loadKlass" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Narrow Klass Pointer +instruct loadNKlass(iRegNNoSp dst, memory mem) +%{ + match(Set dst (LoadNKlass mem)); + + ins_cost(LOAD_COST); + format %{ "lwu $dst, $mem\t# loadNKlass, compressed class ptr, #@loadNKlass" %} + + ins_encode %{ + __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(iload_reg_mem); +%} + +// Load Float +instruct loadF(fRegF dst, memory mem) +%{ + match(Set dst (LoadF mem)); + + ins_cost(LOAD_COST); + format %{ "flw $dst, $mem\t# float, #@loadF" %} + + ins_encode %{ + __ flw(as_FloatRegister($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(fp_load_mem_s); +%} + +// Load Double +instruct loadD(fRegD dst, memory mem) +%{ + match(Set dst (LoadD mem)); + + ins_cost(LOAD_COST); + format %{ "fld $dst, $mem\t# double, #@loadD" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ fld(as_FloatRegister($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(fp_load_mem_d); +%} + +// Load Int Constant +instruct loadConI(iRegINoSp dst, immI src) +%{ + match(Set dst src); + + ins_cost(ALU_COST); + format %{ "li $dst, $src\t# int, #@loadConI" %} + + ins_encode(riscv_enc_li_imm(dst, src)); + + ins_pipe(ialu_imm); +%} + +// Load Long Constant +instruct loadConL(iRegLNoSp dst, immL src) +%{ + match(Set dst src); + + ins_cost(ALU_COST); + format %{ "li $dst, $src\t# long, #@loadConL" %} + + ins_encode(riscv_enc_li_imm(dst, src)); + + ins_pipe(ialu_imm); +%} + +// Load Pointer Constant +instruct loadConP(iRegPNoSp dst, immP con) +%{ + match(Set dst con); + + ins_cost(ALU_COST); + format %{ "mv $dst, $con\t# ptr, #@loadConP" %} + + ins_encode(riscv_enc_mov_p(dst, con)); + + ins_pipe(ialu_imm); +%} + +// Load Null Pointer Constant +instruct loadConP0(iRegPNoSp dst, immP0 con) +%{ + match(Set dst con); + + ins_cost(ALU_COST); + format %{ "mv $dst, $con\t# NULL ptr, #@loadConP0" %} + + ins_encode(riscv_enc_mov_zero(dst)); + + ins_pipe(ialu_imm); +%} + +// Load Pointer Constant One +instruct loadConP1(iRegPNoSp dst, immP_1 con) +%{ + match(Set dst con); + + ins_cost(ALU_COST); + format %{ "mv $dst, $con\t# load ptr constant one, #@loadConP1" %} + + ins_encode(riscv_enc_mov_p1(dst)); + + ins_pipe(ialu_imm); +%} + +// Load Byte Map Base Constant +instruct loadByteMapBase(iRegPNoSp dst, immByteMapBase con) +%{ + match(Set dst con); + ins_cost(ALU_COST); + format %{ "mv $dst, $con\t# Byte Map Base, #@loadByteMapBase" %} + + ins_encode(riscv_enc_mov_byte_map_base(dst)); + + ins_pipe(ialu_imm); +%} + +// Load Narrow Pointer Constant +instruct loadConN(iRegNNoSp dst, immN con) +%{ + match(Set dst con); + + ins_cost(ALU_COST * 4); + format %{ "mv $dst, $con\t# compressed ptr, #@loadConN" %} + + ins_encode(riscv_enc_mov_n(dst, con)); + + ins_pipe(ialu_imm); +%} + +// Load Narrow Null Pointer Constant +instruct loadConN0(iRegNNoSp dst, immN0 con) +%{ + match(Set dst con); + + ins_cost(ALU_COST); + format %{ "mv $dst, $con\t# compressed NULL ptr, #@loadConN0" %} + + ins_encode(riscv_enc_mov_zero(dst)); + + ins_pipe(ialu_imm); +%} + +// Load Narrow Klass Constant +instruct loadConNKlass(iRegNNoSp dst, immNKlass con) +%{ + match(Set dst con); + + ins_cost(ALU_COST * 6); + format %{ "mv $dst, $con\t# compressed klass ptr, #@loadConNKlass" %} + + ins_encode(riscv_enc_mov_nk(dst, con)); + + ins_pipe(ialu_imm); +%} + +// Load Float Constant +instruct loadConF(fRegF dst, immF con) %{ + match(Set dst con); + + ins_cost(LOAD_COST); + format %{ + "flw $dst, [$constantaddress]\t# load from constant table: float=$con, #@loadConF" + %} + + ins_encode %{ + __ flw(as_FloatRegister($dst$$reg), $constantaddress($con)); + %} + + ins_pipe(fp_load_constant_s); +%} + +instruct loadConF0(fRegF dst, immF0 con) %{ + match(Set dst con); + + ins_cost(XFER_COST); + + format %{ "fmv.w.x $dst, zr\t# float, #@loadConF0" %} + + ins_encode %{ + __ fmv_w_x(as_FloatRegister($dst$$reg), zr); + %} + + ins_pipe(fp_load_constant_s); +%} + +// Load Double Constant +instruct loadConD(fRegD dst, immD con) %{ + match(Set dst con); + + ins_cost(LOAD_COST); + format %{ + "fld $dst, [$constantaddress]\t# load from constant table: double=$con, #@loadConD" + %} + + ins_encode %{ + __ fld(as_FloatRegister($dst$$reg), $constantaddress($con)); + %} + + ins_pipe(fp_load_constant_d); +%} + +instruct loadConD0(fRegD dst, immD0 con) %{ + match(Set dst con); + + ins_cost(XFER_COST); + + format %{ "fmv.d.x $dst, zr\t# double, #@loadConD0" %} + + ins_encode %{ + __ fmv_d_x(as_FloatRegister($dst$$reg), zr); + %} + + ins_pipe(fp_load_constant_d); +%} + +// Store Instructions +// Store CMS card-mark Immediate +instruct storeimmCM0(immI0 zero, memory mem) +%{ + match(Set mem (StoreCM mem zero)); + + ins_cost(STORE_COST); + format %{ "storestore (elided)\n\t" + "sb zr, $mem\t# byte, #@storeimmCM0" %} + + ins_encode %{ + __ sb(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store CMS card-mark Immediate with intervening StoreStore +// needed when using CMS with no conditional card marking +instruct storeimmCM0_ordered(immI0 zero, memory mem) +%{ + match(Set mem (StoreCM mem zero)); + + ins_cost(ALU_COST + STORE_COST); + format %{ "membar(StoreStore)\n\t" + "sb zr, $mem\t# byte, #@storeimmCM0_ordered" %} + + ins_encode %{ + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sb(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Byte +instruct storeB(iRegIorL2I src, memory mem) +%{ + match(Set mem (StoreB mem src)); + + ins_cost(STORE_COST); + format %{ "sb $src, $mem\t# byte, #@storeB" %} + + ins_encode %{ + __ sb(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +instruct storeimmB0(immI0 zero, memory mem) +%{ + match(Set mem (StoreB mem zero)); + + ins_cost(STORE_COST); + format %{ "sb zr, $mem\t# byte, #@storeimmB0" %} + + ins_encode %{ + __ sb(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Char/Short +instruct storeC(iRegIorL2I src, memory mem) +%{ + match(Set mem (StoreC mem src)); + + ins_cost(STORE_COST); + format %{ "sh $src, $mem\t# short, #@storeC" %} + + ins_encode %{ + __ sh(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +instruct storeimmC0(immI0 zero, memory mem) +%{ + match(Set mem (StoreC mem zero)); + + ins_cost(STORE_COST); + format %{ "sh zr, $mem\t# short, #@storeimmC0" %} + + ins_encode %{ + __ sh(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Integer +instruct storeI(iRegIorL2I src, memory mem) +%{ + match(Set mem(StoreI mem src)); + + ins_cost(STORE_COST); + format %{ "sw $src, $mem\t# int, #@storeI" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +instruct storeimmI0(immI0 zero, memory mem) +%{ + match(Set mem(StoreI mem zero)); + + ins_cost(STORE_COST); + format %{ "sw zr, $mem\t# int, #@storeimmI0" %} + + ins_encode %{ + __ sw(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Long (64 bit signed) +instruct storeL(iRegL src, memory mem) +%{ + match(Set mem (StoreL mem src)); + + ins_cost(STORE_COST); + format %{ "sd $src, $mem\t# long, #@storeL" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sd(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +// Store Long (64 bit signed) +instruct storeimmL0(immL0 zero, memory mem) +%{ + match(Set mem (StoreL mem zero)); + + ins_cost(STORE_COST); + format %{ "sd zr, $mem\t# long, #@storeimmL0" %} + + ins_encode %{ + __ sd(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Pointer +instruct storeP(iRegP src, memory mem) +%{ + match(Set mem (StoreP mem src)); + + ins_cost(STORE_COST); + format %{ "sd $src, $mem\t# ptr, #@storeP" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sd(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +// Store Pointer +instruct storeimmP0(immP0 zero, memory mem) +%{ + match(Set mem (StoreP mem zero)); + + ins_cost(STORE_COST); + format %{ "sd zr, $mem\t# ptr, #@storeimmP0" %} + + ins_encode %{ + __ sd(zr, Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_mem); +%} + +// Store Compressed Pointer +instruct storeN(iRegN src, memory mem) +%{ + match(Set mem (StoreN mem src)); + + ins_cost(STORE_COST); + format %{ "sw $src, $mem\t# compressed ptr, #@storeN" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem) +%{ + match(Set mem (StoreN mem zero)); + + ins_cost(STORE_COST); + format %{ "sw rheapbase, $mem\t# compressed ptr (rheapbase==0), #@storeImmN0" %} + + ins_encode %{ + __ sw(as_Register($heapbase$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +// Store Float +instruct storeF(fRegF src, memory mem) +%{ + match(Set mem (StoreF mem src)); + + ins_cost(STORE_COST); + format %{ "fsw $src, $mem\t# float, #@storeF" %} + + ins_encode %{ + __ fsw(as_FloatRegister($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(fp_store_reg_s); +%} + +// Store Double +instruct storeD(fRegD src, memory mem) +%{ + match(Set mem (StoreD mem src)); + + ins_cost(STORE_COST); + format %{ "fsd $src, $mem\t# double, #@storeD" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ fsd(as_FloatRegister($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(fp_store_reg_d); +%} + +// Store Compressed Klass Pointer +instruct storeNKlass(iRegN src, memory mem) +%{ + match(Set mem (StoreNKlass mem src)); + + ins_cost(STORE_COST); + format %{ "sw $src, $mem\t# compressed klass ptr, #@storeNKlass" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp)); + %} + + ins_pipe(istore_reg_mem); +%} + +// ============================================================================ +// Atomic operation instructions +// +// Intel and SPARC both implement Ideal Node LoadPLocked and +// Store{PIL}Conditional instructions using a normal load for the +// LoadPLocked and a CAS for the Store{PIL}Conditional. +// +// The ideal code appears only to use LoadPLocked/storePConditional as a +// pair to lock object allocations from Eden space when not using +// TLABs. +// +// There does not appear to be a Load{IL}Locked Ideal Node and the +// Ideal code appears to use Store{IL}Conditional as an alias for CAS +// and to use StoreIConditional only for 32-bit and StoreLConditional +// only for 64-bit. +// +// We implement LoadPLocked and storePConditional instructions using, +// respectively the RISCV hw load-reserve and store-conditional +// instructions. Whereas we must implement each of +// Store{IL}Conditional using a CAS which employs a pair of +// instructions comprising a load-reserve followed by a +// store-conditional. + + +// Locked-load (load reserved) of the current heap-top +// used when updating the eden heap top +// implemented using lr_d on RISCV64 +instruct loadPLocked(iRegPNoSp dst, indirect mem) +%{ + match(Set dst (LoadPLocked mem)); + + ins_cost(ALU_COST * 2 + LOAD_COST); + + format %{ "lr.d $dst, $mem\t# ptr load reserved, #@loadPLocked" %} + + ins_encode %{ + __ la(t0, Address(as_Register($mem$$base), $mem$$disp)); + __ lr_d($dst$$Register, t0, Assembler::aq); + %} + + ins_pipe(pipe_serial); +%} + +// Conditional-store of the updated heap-top. +// Used during allocation of the shared heap. +// implemented using sc_d on RISCV64. +instruct storePConditional(memory heap_top_ptr, iRegP oldval, iRegP newval, rFlagsReg cr) +%{ + match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); + + ins_cost(ALU_COST * 2 + STORE_COST); + + format %{ + "sc_d t1, $newval $heap_top_ptr,\t# ptr store conditional, #@storePConditional" + %} + + ins_encode %{ + __ la(t0, Address(as_Register($heap_top_ptr$$base), $heap_top_ptr$$disp)); + __ sc_d($cr$$Register, $newval$$Register, t0, Assembler::rl); + %} + + ins_pipe(pipe_serial); +%} + +instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) +%{ + match(Set cr (StoreLConditional mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + 2 * BRANCH_COST); + + format %{ + "cmpxchg t1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval" + "xorr $cr, $cr, $oldval\t# $cr == 0 on successful write, #@storeLConditional" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $cr$$Register); + __ xorr($cr$$Register,$cr$$Register, $oldval$$Register); + %} + + ins_pipe(pipe_slow); +%} + +// storeIConditional also has acquire semantics, for no better reason +// than matching storeLConditional. +instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) +%{ + match(Set cr (StoreIConditional mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2); + + format %{ + "cmpxchgw t1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval" + "xorr $cr, $cr, $oldval\t# $cr == 0 on successful write, #@storeIConditional" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $cr$$Register); + __ xorr($cr$$Register,$cr$$Register, $oldval$$Register); + %} + + ins_pipe(pipe_slow); +%} + +// standard CompareAndSwapX when we are using barriers +// these have higher priority than the rules selected by a predicate +instruct compareAndSwapB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndSwapB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 10 + BRANCH_COST * 4); + + effect(TEMP_DEF res, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapB" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndSwapS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 11 + BRANCH_COST * 4); + + effect(TEMP_DEF res, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapS" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval) +%{ + match(Set res (CompareAndSwapI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapI" + %} + + ins_encode(riscv_enc_cmpxchgw(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval) +%{ + match(Set res (CompareAndSwapL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapL" + %} + + ins_encode(riscv_enc_cmpxchg(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(n->as_LoadStore()->barrier_data() == 0); + + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapP" + %} + + ins_encode(riscv_enc_cmpxchg(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval) +%{ + match(Set res (CompareAndSwapN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 8 + BRANCH_COST * 4); + + format %{ + "cmpxchg $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapN" + %} + + ins_encode(riscv_enc_cmpxchgn(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +// alternative CompareAndSwapX when we are eliding barriers +instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 10 + BRANCH_COST * 4); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapBAcq" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 11 + BRANCH_COST * 4); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapSAcq" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, + true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapIAcq" + %} + + ins_encode(riscv_enc_cmpxchgw_acq(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapLAcq" + %} + + ins_encode(riscv_enc_cmpxchg_acq(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); + + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapPAcq" + %} + + ins_encode(riscv_enc_cmpxchg_acq(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 8 + BRANCH_COST * 4); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval\n\t" + "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapNAcq" + %} + + ins_encode(riscv_enc_cmpxchgn_acq(res, mem, oldval, newval)); + + ins_pipe(pipe_slow); +%} + +// Sundry CAS operations. Note that release is always true, +// regardless of the memory ordering of the CAS. This is because we +// need the volatile case to be sequentially consistent but there is +// no trailing StoreLoad barrier emitted by C2. Unfortunately we +// can't check the type of memory ordering here, so we always emit a +// sc_d(w) with rl bit set. +instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndExchangeB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST * 5); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeB" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndExchangeS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST * 6); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeS" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + match(Set res (CompareAndExchangeI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeI" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeL(iRegLNoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + match(Set res (CompareAndExchangeL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeL" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + match(Set res (CompareAndExchangeN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST * 3); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeN" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeP" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST * 5); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeBAcq" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST * 6); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeSAcq" + %} + + ins_encode %{ + __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeIAcq" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeLAcq(iRegLNoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeLAcq" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); + + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); + + effect(TEMP_DEF res); + + format %{ + "cmpxchg_acq $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq" + %} + + ins_encode %{ + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (WeakCompareAndSwapB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 6); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapB" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + match(Set res (WeakCompareAndSwapS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 7); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapS" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + match(Set res (WeakCompareAndSwapI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapI" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + match(Set res (WeakCompareAndSwapL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapL" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + match(Set res (WeakCompareAndSwapN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 4); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapN" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapP" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapB mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 6); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapBAcq" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, + iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapS mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 7); + + effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapSAcq" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapI mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapIAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapL mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapLAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapN mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 4); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapNAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ + predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); + + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t" + "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapPAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); + __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) +%{ + match(Set prev (GetAndSetI mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchgw $prev, $newv, [$mem]\t#@get_and_setI" %} + + ins_encode %{ + __ atomic_xchgw($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) +%{ + match(Set prev (GetAndSetL mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchg $prev, $newv, [$mem]\t#@get_and_setL" %} + + ins_encode %{ + __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) +%{ + match(Set prev (GetAndSetN mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchgwu $prev, $newv, [$mem]\t#@get_and_setN" %} + + ins_encode %{ + __ atomic_xchgwu($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) +%{ + predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set prev (GetAndSetP mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchg $prev, $newv, [$mem]\t#@get_and_setP" %} + + ins_encode %{ + __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setIAcq(indirect mem, iRegI newv, iRegINoSp prev) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set prev (GetAndSetI mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchgw_acq $prev, $newv, [$mem]\t#@get_and_setIAcq" %} + + ins_encode %{ + __ atomic_xchgalw($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setLAcq(indirect mem, iRegL newv, iRegLNoSp prev) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set prev (GetAndSetL mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchg_acq $prev, $newv, [$mem]\t#@get_and_setLAcq" %} + + ins_encode %{ + __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setNAcq(indirect mem, iRegN newv, iRegINoSp prev) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set prev (GetAndSetN mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchgwu_acq $prev, $newv, [$mem]\t#@get_and_setNAcq" %} + + ins_encode %{ + __ atomic_xchgalwu($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev) +%{ + predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); + + match(Set prev (GetAndSetP mem newv)); + + ins_cost(ALU_COST); + + format %{ "atomic_xchg_acq $prev, $newv, [$mem]\t#@get_and_setPAcq" %} + + ins_encode %{ + __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addL(indirect mem, iRegLNoSp newval, iRegL incr) +%{ + match(Set newval (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL $newval, [$mem], $incr\t#@get_and_addL" %} + + ins_encode %{ + __ atomic_add($newval$$Register, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addL_no_res(indirect mem, Universe dummy, iRegL incr) +%{ + predicate(n->as_LoadStore()->result_not_used()); + + match(Set dummy (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL [$mem], $incr\t#@get_and_addL_no_res" %} + + ins_encode %{ + __ atomic_add(noreg, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addLi(indirect mem, iRegLNoSp newval, immLAdd incr) +%{ + match(Set newval (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL $newval, [$mem], $incr\t#@get_and_addLi" %} + + ins_encode %{ + __ atomic_add($newval$$Register, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addLi_no_res(indirect mem, Universe dummy, immLAdd incr) +%{ + predicate(n->as_LoadStore()->result_not_used()); + + match(Set dummy (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL [$mem], $incr\t#@get_and_addLi_no_res" %} + + ins_encode %{ + __ atomic_add(noreg, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addI(indirect mem, iRegINoSp newval, iRegIorL2I incr) +%{ + match(Set newval (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI $newval, [$mem], $incr\t#@get_and_addI" %} + + ins_encode %{ + __ atomic_addw($newval$$Register, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addI_no_res(indirect mem, Universe dummy, iRegIorL2I incr) +%{ + predicate(n->as_LoadStore()->result_not_used()); + + match(Set dummy (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI [$mem], $incr\t#@get_and_addI_no_res" %} + + ins_encode %{ + __ atomic_addw(noreg, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addIi(indirect mem, iRegINoSp newval, immIAdd incr) +%{ + match(Set newval (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI $newval, [$mem], $incr\t#@get_and_addIi" %} + + ins_encode %{ + __ atomic_addw($newval$$Register, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addIi_no_res(indirect mem, Universe dummy, immIAdd incr) +%{ + predicate(n->as_LoadStore()->result_not_used()); + + match(Set dummy (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI [$mem], $incr\t#@get_and_addIi_no_res" %} + + ins_encode %{ + __ atomic_addw(noreg, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addLAcq(indirect mem, iRegLNoSp newval, iRegL incr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set newval (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL_acq $newval, [$mem], $incr\t#@get_and_addLAcq" %} + + ins_encode %{ + __ atomic_addal($newval$$Register, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addL_no_resAcq(indirect mem, Universe dummy, iRegL incr) %{ + predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n)); + + match(Set dummy (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL_acq [$mem], $incr\t#@get_and_addL_no_resAcq" %} + + ins_encode %{ + __ atomic_addal(noreg, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addLiAcq(indirect mem, iRegLNoSp newval, immLAdd incr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set newval (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL_acq $newval, [$mem], $incr\t#@get_and_addLiAcq" %} + + ins_encode %{ + __ atomic_addal($newval$$Register, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addLi_no_resAcq(indirect mem, Universe dummy, immLAdd incr) +%{ + predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n)); + + match(Set dummy (GetAndAddL mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addL_acq [$mem], $incr\t#@get_and_addLi_no_resAcq" %} + + ins_encode %{ + __ atomic_addal(noreg, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addIAcq(indirect mem, iRegINoSp newval, iRegIorL2I incr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set newval (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI_acq $newval, [$mem], $incr\t#@get_and_addIAcq" %} + + ins_encode %{ + __ atomic_addalw($newval$$Register, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addI_no_resAcq(indirect mem, Universe dummy, iRegIorL2I incr) +%{ + predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n)); + + match(Set dummy (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI_acq [$mem], $incr\t#@get_and_addI_no_resAcq" %} + + ins_encode %{ + __ atomic_addalw(noreg, $incr$$Register, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addIiAcq(indirect mem, iRegINoSp newval, immIAdd incr) +%{ + predicate(needs_acquiring_load_reserved(n)); + + match(Set newval (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI_acq $newval, [$mem], $incr\t#@get_and_addIiAcq" %} + + ins_encode %{ + __ atomic_addalw($newval$$Register, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +instruct get_and_addIi_no_resAcq(indirect mem, Universe dummy, immIAdd incr) +%{ + predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n)); + + match(Set dummy (GetAndAddI mem incr)); + + ins_cost(ALU_COST); + + format %{ "get_and_addI_acq [$mem], $incr\t#@get_and_addIi_no_resAcq" %} + + ins_encode %{ + __ atomic_addalw(noreg, $incr$$constant, as_Register($mem$$base)); + %} + + ins_pipe(pipe_serial); +%} + +// ============================================================================ +// Arithmetic Instructions +// + +// Integer Addition + +// TODO +// these currently employ operations which do not set CR and hence are +// not flagged as killing CR but we would like to isolate the cases +// where we want to set flags from those where we don't. need to work +// out how to do that. +instruct addI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (AddI src1 src2)); + + ins_cost(ALU_COST); + format %{ "addw $dst, $src1, $src2\t#@addI_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ addw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct addI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAdd src2) %{ + match(Set dst (AddI src1 src2)); + + ins_cost(ALU_COST); + format %{ "addiw $dst, $src1, $src2\t#@addI_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + int32_t con = (int32_t)$src2$$constant; + __ addiw(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +instruct addI_reg_imm_l2i(iRegINoSp dst, iRegL src1, immIAdd src2) %{ + match(Set dst (AddI (ConvL2I src1) src2)); + + ins_cost(ALU_COST); + format %{ "addiw $dst, $src1, $src2\t#@addI_reg_imm_l2i" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ addiw(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Pointer Addition +instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegL src2) %{ + match(Set dst (AddP src1 src2)); + + ins_cost(ALU_COST); + format %{ "add $dst, $src1, $src2\t# ptr, #@addP_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ add(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// If we shift more than 32 bits, we need not convert I2L. +instruct lShiftL_regI_immGE32(iRegLNoSp dst, iRegI src, uimmI6_ge32 scale) %{ + match(Set dst (LShiftL (ConvI2L src) scale)); + ins_cost(ALU_COST); + format %{ "slli $dst, $src, $scale & 63\t#@lShiftL_regI_immGE32" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ slli(as_Register($dst$$reg), as_Register($src$$reg), $scale$$constant & 63); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Pointer Immediate Addition +// n.b. this needs to be more expensive than using an indirect memory +// operand +instruct addP_reg_imm(iRegPNoSp dst, iRegP src1, immLAdd src2) %{ + match(Set dst (AddP src1 src2)); + ins_cost(ALU_COST); + format %{ "addi $dst, $src1, $src2\t# ptr, #@addP_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // src2 is imm, so actually call the addi + __ add(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Long Addition +instruct addL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (AddL src1 src2)); + ins_cost(ALU_COST); + format %{ "add $dst, $src1, $src2\t#@addL_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ add(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// No constant pool entries requiredLong Immediate Addition. +instruct addL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{ + match(Set dst (AddL src1 src2)); + ins_cost(ALU_COST); + format %{ "addi $dst, $src1, $src2\t#@addL_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // src2 is imm, so actually call the addi + __ add(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Integer Subtraction +instruct subI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (SubI src1 src2)); + + ins_cost(ALU_COST); + format %{ "subw $dst, $src1, $src2\t#@subI_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ subw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate Subtraction +instruct subI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immISub src2) %{ + match(Set dst (SubI src1 src2)); + + ins_cost(ALU_COST); + format %{ "addiw $dst, $src1, -$src2\t#@subI_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // src2 is imm, so actually call the addiw + __ subw(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Long Subtraction +instruct subL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (SubL src1 src2)); + ins_cost(ALU_COST); + format %{ "sub $dst, $src1, $src2\t#@subL_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sub(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// No constant pool entries requiredLong Immediate Subtraction. +instruct subL_reg_imm(iRegLNoSp dst, iRegL src1, immLSub src2) %{ + match(Set dst (SubL src1 src2)); + ins_cost(ALU_COST); + format %{ "addi $dst, $src1, -$src2\t#@subL_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // src2 is imm, so actually call the addi + __ sub(as_Register($dst$$reg), + as_Register($src1$$reg), + $src2$$constant); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Integer Negation (special case for sub) + +instruct negI_reg(iRegINoSp dst, iRegIorL2I src, immI0 zero) %{ + match(Set dst (SubI zero src)); + ins_cost(ALU_COST); + format %{ "subw $dst, x0, $src\t# int, #@negI_reg" %} + + ins_encode %{ + // actually call the subw + __ negw(as_Register($dst$$reg), + as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Long Negation + +instruct negL_reg(iRegLNoSp dst, iRegL src, immL0 zero) %{ + match(Set dst (SubL zero src)); + ins_cost(ALU_COST); + format %{ "sub $dst, x0, $src\t# long, #@negL_reg" %} + + ins_encode %{ + // actually call the sub + __ neg(as_Register($dst$$reg), + as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Integer Multiply + +instruct mulI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (MulI src1 src2)); + ins_cost(IMUL_COST); + format %{ "mulw $dst, $src1, $src2\t#@mulI" %} + + //this means 2 word multi, and no sign extend to 64 bits + ins_encode %{ + // riscv64 mulw will sign-extension to high 32 bits in dst reg + __ mulw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(imul_reg_reg); +%} + +// Long Multiply + +instruct mulL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (MulL src1 src2)); + ins_cost(IMUL_COST); + format %{ "mul $dst, $src1, $src2\t#@mulL" %} + + ins_encode %{ + __ mul(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(lmul_reg_reg); +%} + +instruct mulHiL_rReg(iRegLNoSp dst, iRegL src1, iRegL src2) +%{ + match(Set dst (MulHiL src1 src2)); + ins_cost(IMUL_COST); + format %{ "mulh $dst, $src1, $src2\t# mulhi, #@mulHiL_rReg" %} + + ins_encode %{ + __ mulh(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(lmul_reg_reg); +%} + +// Integer Divide + +instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (DivI src1 src2)); + ins_cost(IDIVSI_COST); + format %{ "divw $dst, $src1, $src2\t#@divI"%} + + ins_encode(riscv_enc_divw(dst, src1, src2)); + ins_pipe(idiv_reg_reg); +%} + +instruct signExtract(iRegINoSp dst, iRegIorL2I src1, immI_31 div1, immI_31 div2) %{ + match(Set dst (URShiftI (RShiftI src1 div1) div2)); + ins_cost(ALU_COST); + format %{ "srliw $dst, $src1, $div1\t# int signExtract, #@signExtract" %} + + ins_encode %{ + __ srliw(as_Register($dst$$reg), as_Register($src1$$reg), 31); + %} + ins_pipe(ialu_reg_shift); +%} + +// Long Divide + +instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (DivL src1 src2)); + ins_cost(IDIVDI_COST); + format %{ "div $dst, $src1, $src2\t#@divL" %} + + ins_encode(riscv_enc_div(dst, src1, src2)); + ins_pipe(ldiv_reg_reg); +%} + +instruct signExtractL(iRegLNoSp dst, iRegL src1, immI_63 div1, immI_63 div2) %{ + match(Set dst (URShiftL (RShiftL src1 div1) div2)); + ins_cost(ALU_COST); + format %{ "srli $dst, $src1, $div1\t# long signExtract, #@signExtractL" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ srli(as_Register($dst$$reg), as_Register($src1$$reg), 63); + %} + ins_pipe(ialu_reg_shift); +%} + +// Integer Remainder + +instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (ModI src1 src2)); + ins_cost(IDIVSI_COST); + format %{ "remw $dst, $src1, $src2\t#@modI" %} + + ins_encode(riscv_enc_modw(dst, src1, src2)); + ins_pipe(ialu_reg_reg); +%} + +// Long Remainder + +instruct modL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (ModL src1 src2)); + ins_cost(IDIVDI_COST); + format %{ "rem $dst, $src1, $src2\t#@modL" %} + + ins_encode(riscv_enc_mod(dst, src1, src2)); + ins_pipe(ialu_reg_reg); +%} + +// Integer Shifts + +// Shift Left Register +// In RV64I, only the low 5 bits of src2 are considered for the shift amount +instruct lShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (LShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "sllw $dst, $src1, $src2\t#@lShiftI_reg_reg" %} + + ins_encode %{ + __ sllw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Left Immediate +instruct lShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ + match(Set dst (LShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "slliw $dst, $src1, ($src2 & 0x1f)\t#@lShiftI_reg_imm" %} + + ins_encode %{ + // the shift amount is encoded in the lower + // 5 bits of the I-immediate field for RV32I + __ slliw(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x1f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Shift Right Logical Register +// In RV64I, only the low 5 bits of src2 are considered for the shift amount +instruct urShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (URShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "srlw $dst, $src1, $src2\t#@urShiftI_reg_reg" %} + + ins_encode %{ + __ srlw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Right Logical Immediate +instruct urShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ + match(Set dst (URShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "srliw $dst, $src1, ($src2 & 0x1f)\t#@urShiftI_reg_imm" %} + + ins_encode %{ + // the shift amount is encoded in the lower + // 6 bits of the I-immediate field for RV64I + __ srliw(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x1f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Shift Right Arithmetic Register +// In RV64I, only the low 5 bits of src2 are considered for the shift amount +instruct rShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ + match(Set dst (RShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "sraw $dst, $src1, $src2\t#@rShiftI_reg_reg" %} + + ins_encode %{ + // riscv will sign-ext dst high 32 bits + __ sraw(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Right Arithmetic Immediate +instruct rShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ + match(Set dst (RShiftI src1 src2)); + ins_cost(ALU_COST); + format %{ "sraiw $dst, $src1, ($src2 & 0x1f)\t#@rShiftI_reg_imm" %} + + ins_encode %{ + // riscv will sign-ext dst high 32 bits + __ sraiw(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x1f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Long Shifts + +// Shift Left Register +// In RV64I, only the low 6 bits of src2 are considered for the shift amount +instruct lShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ + match(Set dst (LShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "sll $dst, $src1, $src2\t#@lShiftL_reg_reg" %} + + ins_encode %{ + __ sll(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Left Immediate +instruct lShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{ + match(Set dst (LShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "slli $dst, $src1, ($src2 & 0x3f)\t#@lShiftL_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // the shift amount is encoded in the lower + // 6 bits of the I-immediate field for RV64I + __ slli(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x3f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Shift Right Logical Register +// In RV64I, only the low 6 bits of src2 are considered for the shift amount +instruct urShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ + match(Set dst (URShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "srl $dst, $src1, $src2\t#@urShiftL_reg_reg" %} + + ins_encode %{ + __ srl(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Right Logical Immediate +instruct urShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{ + match(Set dst (URShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "srli $dst, $src1, ($src2 & 0x3f)\t#@urShiftL_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // the shift amount is encoded in the lower + // 6 bits of the I-immediate field for RV64I + __ srli(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x3f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// A special-case pattern for card table stores. +instruct urShiftP_reg_imm(iRegLNoSp dst, iRegP src1, immI src2) %{ + match(Set dst (URShiftL (CastP2X src1) src2)); + + ins_cost(ALU_COST); + format %{ "srli $dst, p2x($src1), ($src2 & 0x3f)\t#@urShiftP_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // the shift amount is encoded in the lower + // 6 bits of the I-immediate field for RV64I + __ srli(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x3f); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Shift Right Arithmetic Register +// In RV64I, only the low 6 bits of src2 are considered for the shift amount +instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ + match(Set dst (RShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "sra $dst, $src1, $src2\t#@rShiftL_reg_reg" %} + + ins_encode %{ + __ sra(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg_vshift); +%} + +// Shift Right Arithmetic Immediate +instruct rShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{ + match(Set dst (RShiftL src1 src2)); + + ins_cost(ALU_COST); + format %{ "srai $dst, $src1, ($src2 & 0x3f)\t#@rShiftL_reg_imm" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + // the shift amount is encoded in the lower + // 6 bits of the I-immediate field for RV64I + __ srai(as_Register($dst$$reg), + as_Register($src1$$reg), + (unsigned) $src2$$constant & 0x3f); + %} + + ins_pipe(ialu_reg_shift); +%} + +instruct regI_not_reg(iRegINoSp dst, iRegI src1, immI_M1 m1) %{ + match(Set dst (XorI src1 m1)); + ins_cost(ALU_COST); + format %{ "xori $dst, $src1, -1\t#@regI_not_reg" %} + + ins_encode %{ + __ xori(as_Register($dst$$reg), as_Register($src1$$reg), -1); + %} + + ins_pipe(ialu_reg); +%} + +instruct regL_not_reg(iRegLNoSp dst, iRegL src1, immL_M1 m1) %{ + match(Set dst (XorL src1 m1)); + ins_cost(ALU_COST); + format %{ "xori $dst, $src1, -1\t#@regL_not_reg" %} + + ins_encode %{ + __ xori(as_Register($dst$$reg), as_Register($src1$$reg), -1); + %} + + ins_pipe(ialu_reg); +%} + + +// ============================================================================ +// Floating Point Arithmetic Instructions + +instruct addF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (AddF src1 src2)); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fadd.s $dst, $src1, $src2\t#@addF_reg_reg" %} + + ins_encode %{ + __ fadd_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_s); +%} + +instruct addD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (AddD src1 src2)); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fadd.d $dst, $src1, $src2\t#@addD_reg_reg" %} + + ins_encode %{ + __ fadd_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_d); +%} + +instruct subF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (SubF src1 src2)); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fsub.s $dst, $src1, $src2\t#@subF_reg_reg" %} + + ins_encode %{ + __ fsub_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_s); +%} + +instruct subD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (SubD src1 src2)); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fsub.d $dst, $src1, $src2\t#@subD_reg_reg" %} + + ins_encode %{ + __ fsub_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_d); +%} + +instruct mulF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (MulF src1 src2)); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fmul.s $dst, $src1, $src2\t#@mulF_reg_reg" %} + + ins_encode %{ + __ fmul_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_s); +%} + +instruct mulD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (MulD src1 src2)); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fmul.d $dst, $src1, $src2\t#@mulD_reg_reg" %} + + ins_encode %{ + __ fmul_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_dop_reg_reg_d); +%} + +// src1 * src2 + src3 +instruct maddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{ + predicate(UseFMA); + match(Set dst (FmaF src3 (Binary src1 src2))); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fmadd.s $dst, $src1, $src2, $src3\t#@maddF_reg_reg" %} + + ins_encode %{ + __ fmadd_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// src1 * src2 + src3 +instruct maddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{ + predicate(UseFMA); + match(Set dst (FmaD src3 (Binary src1 src2))); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fmadd.d $dst, $src1, $src2, $src3\t#@maddD_reg_reg" %} + + ins_encode %{ + __ fmadd_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// src1 * src2 - src3 +instruct msubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{ + predicate(UseFMA); + match(Set dst (FmaF (NegF src3) (Binary src1 src2))); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fmsub.s $dst, $src1, $src2, $src3\t#@msubF_reg_reg" %} + + ins_encode %{ + __ fmsub_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// src1 * src2 - src3 +instruct msubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{ + predicate(UseFMA); + match(Set dst (FmaD (NegD src3) (Binary src1 src2))); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fmsub.d $dst, $src1, $src2, $src3\t#@msubD_reg_reg" %} + + ins_encode %{ + __ fmsub_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// -src1 * src2 + src3 +instruct nmsubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{ + predicate(UseFMA); + match(Set dst (FmaF src3 (Binary (NegF src1) src2))); + match(Set dst (FmaF src3 (Binary src1 (NegF src2)))); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fnmsub.s $dst, $src1, $src2, $src3\t#@nmsubF_reg_reg" %} + + ins_encode %{ + __ fnmsub_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// -src1 * src2 + src3 +instruct nmsubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{ + predicate(UseFMA); + match(Set dst (FmaD src3 (Binary (NegD src1) src2))); + match(Set dst (FmaD src3 (Binary src1 (NegD src2)))); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fnmsub.d $dst, $src1, $src2, $src3\t#@nmsubD_reg_reg" %} + + ins_encode %{ + __ fnmsub_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// -src1 * src2 - src3 +instruct nmaddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{ + predicate(UseFMA); + match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2))); + match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2)))); + + ins_cost(FMUL_SINGLE_COST); + format %{ "fnmadd.s $dst, $src1, $src2, $src3\t#@nmaddF_reg_reg" %} + + ins_encode %{ + __ fnmadd_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// -src1 * src2 - src3 +instruct nmaddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{ + predicate(UseFMA); + match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2))); + match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2)))); + + ins_cost(FMUL_DOUBLE_COST); + format %{ "fnmadd.d $dst, $src1, $src2, $src3\t#@nmaddD_reg_reg" %} + + ins_encode %{ + __ fnmadd_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), + as_FloatRegister($src3$$reg)); + %} + + ins_pipe(pipe_class_default); +%} + +// Math.max(FF)F +instruct maxF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (MaxF src1 src2)); + effect(TEMP_DEF dst); + + format %{ "maxF $dst, $src1, $src2" %} + + ins_encode %{ + __ minmax_FD(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), + false /* is_double */, false /* is_min */); + %} + + ins_pipe(fp_dop_reg_reg_s); +%} + +// Math.min(FF)F +instruct minF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (MinF src1 src2)); + effect(TEMP_DEF dst); + + format %{ "minF $dst, $src1, $src2" %} + + ins_encode %{ + __ minmax_FD(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), + false /* is_double */, true /* is_min */); + %} + + ins_pipe(fp_dop_reg_reg_s); +%} + +// Math.max(DD)D +instruct maxD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (MaxD src1 src2)); + effect(TEMP_DEF dst); + + format %{ "maxD $dst, $src1, $src2" %} + + ins_encode %{ + __ minmax_FD(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), + true /* is_double */, false /* is_min */); + %} + + ins_pipe(fp_dop_reg_reg_d); +%} + +// Math.min(DD)D +instruct minD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (MinD src1 src2)); + effect(TEMP_DEF dst); + + format %{ "minD $dst, $src1, $src2" %} + + ins_encode %{ + __ minmax_FD(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), + true /* is_double */, true /* is_min */); + %} + + ins_pipe(fp_dop_reg_reg_d); +%} + +instruct divF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{ + match(Set dst (DivF src1 src2)); + + ins_cost(FDIV_COST); + format %{ "fdiv.s $dst, $src1, $src2\t#@divF_reg_reg" %} + + ins_encode %{ + __ fdiv_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_div_s); +%} + +instruct divD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{ + match(Set dst (DivD src1 src2)); + + ins_cost(FDIV_COST); + format %{ "fdiv.d $dst, $src1, $src2\t#@divD_reg_reg" %} + + ins_encode %{ + __ fdiv_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + + ins_pipe(fp_div_d); +%} + +instruct negF_reg_reg(fRegF dst, fRegF src) %{ + match(Set dst (NegF src)); + + ins_cost(XFER_COST); + format %{ "fsgnjn.s $dst, $src, $src\t#@negF_reg_reg" %} + + ins_encode %{ + __ fneg_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_uop_s); +%} + +instruct negD_reg_reg(fRegD dst, fRegD src) %{ + match(Set dst (NegD src)); + + ins_cost(XFER_COST); + format %{ "fsgnjn.d $dst, $src, $src\t#@negD_reg_reg" %} + + ins_encode %{ + __ fneg_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_uop_d); +%} + +instruct absI_reg(iRegINoSp dst, iRegIorL2I src) %{ + match(Set dst (AbsI src)); + + ins_cost(ALU_COST * 3); + format %{ + "sraiw t0, $src, 0x1f\n\t" + "addw $dst, $src, t0\n\t" + "xorr $dst, $dst, t0\t#@absI_reg" + %} + + ins_encode %{ + __ sraiw(t0, as_Register($src$$reg), 0x1f); + __ addw(as_Register($dst$$reg), as_Register($src$$reg), t0); + __ xorr(as_Register($dst$$reg), as_Register($dst$$reg), t0); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct absL_reg(iRegLNoSp dst, iRegL src) %{ + match(Set dst (AbsL src)); + + ins_cost(ALU_COST * 3); + format %{ + "srai t0, $src, 0x3f\n\t" + "add $dst, $src, t0\n\t" + "xorr $dst, $dst, t0\t#@absL_reg" + %} + + ins_encode %{ + __ srai(t0, as_Register($src$$reg), 0x3f); + __ add(as_Register($dst$$reg), as_Register($src$$reg), t0); + __ xorr(as_Register($dst$$reg), as_Register($dst$$reg), t0); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct absF_reg(fRegF dst, fRegF src) %{ + match(Set dst (AbsF src)); + + ins_cost(XFER_COST); + format %{ "fsgnjx.s $dst, $src, $src\t#@absF_reg" %} + ins_encode %{ + __ fabs_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_uop_s); +%} + +instruct absD_reg(fRegD dst, fRegD src) %{ + match(Set dst (AbsD src)); + + ins_cost(XFER_COST); + format %{ "fsgnjx.d $dst, $src, $src\t#@absD_reg" %} + ins_encode %{ + __ fabs_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_uop_d); +%} + +instruct sqrtF_reg(fRegF dst, fRegF src) %{ + match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); + + ins_cost(FSQRT_COST); + format %{ "fsqrt.s $dst, $src\t#@sqrtF_reg" %} + ins_encode %{ + __ fsqrt_s(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_sqrt_s); +%} + +instruct sqrtD_reg(fRegD dst, fRegD src) %{ + match(Set dst (SqrtD src)); + + ins_cost(FSQRT_COST); + format %{ "fsqrt.d $dst, $src\t#@sqrtD_reg" %} + ins_encode %{ + __ fsqrt_d(as_FloatRegister($dst$$reg), + as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_sqrt_d); +%} + +// Arithmetic Instructions End + +// ============================================================================ +// Logical Instructions + +// Register And +instruct andI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{ + match(Set dst (AndI src1 src2)); + + format %{ "andr $dst, $src1, $src2\t#@andI_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ andr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate And +instruct andI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{ + match(Set dst (AndI src1 src2)); + + format %{ "andi $dst, $src1, $src2\t#@andI_reg_imm" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ andi(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Register Or +instruct orI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{ + match(Set dst (OrI src1 src2)); + + format %{ "orr $dst, $src1, $src2\t#@orI_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ orr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate Or +instruct orI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{ + match(Set dst (OrI src1 src2)); + + format %{ "ori $dst, $src1, $src2\t#@orI_reg_imm" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ ori(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Register Xor +instruct xorI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{ + match(Set dst (XorI src1 src2)); + + format %{ "xorr $dst, $src1, $src2\t#@xorI_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ xorr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate Xor +instruct xorI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{ + match(Set dst (XorI src1 src2)); + + format %{ "xori $dst, $src1, $src2\t#@xorI_reg_imm" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ xori(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Register And Long +instruct andL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (AndL src1 src2)); + + format %{ "andr $dst, $src1, $src2\t#@andL_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ andr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate And Long +instruct andL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{ + match(Set dst (AndL src1 src2)); + + format %{ "andi $dst, $src1, $src2\t#@andL_reg_imm" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ andi(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Register Or Long +instruct orL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (OrL src1 src2)); + + format %{ "orr $dst, $src1, $src2\t#@orL_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ orr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate Or Long +instruct orL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{ + match(Set dst (OrL src1 src2)); + + format %{ "ori $dst, $src1, $src2\t#@orL_reg_imm" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ ori(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// Register Xor Long +instruct xorL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{ + match(Set dst (XorL src1 src2)); + + format %{ "xorr $dst, $src1, $src2\t#@xorL_reg_reg" %} + + ins_cost(ALU_COST); + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ xorr(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Immediate Xor Long +instruct xorL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{ + match(Set dst (XorL src1 src2)); + + ins_cost(ALU_COST); + format %{ "xori $dst, $src1, $src2\t#@xorL_reg_imm" %} + + ins_encode %{ + __ xori(as_Register($dst$$reg), + as_Register($src1$$reg), + (int32_t)($src2$$constant)); + %} + + ins_pipe(ialu_reg_imm); +%} + +// ============================================================================ +// BSWAP Instructions + +instruct bytes_reverse_int(iRegINoSp dst, iRegIorL2I src, rFlagsReg cr) %{ + match(Set dst (ReverseBytesI src)); + effect(TEMP cr); + + ins_cost(ALU_COST * 13); + format %{ "revb_w_w $dst, $src\t#@bytes_reverse_int" %} + + ins_encode %{ + __ revb_w_w(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_long(iRegLNoSp dst, iRegL src, rFlagsReg cr) %{ + match(Set dst (ReverseBytesL src)); + effect(TEMP cr); + + ins_cost(ALU_COST * 29); + format %{ "revb $dst, $src\t#@bytes_reverse_long" %} + + ins_encode %{ + __ revb(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_unsigned_short(iRegINoSp dst, iRegIorL2I src) %{ + match(Set dst (ReverseBytesUS src)); + + ins_cost(ALU_COST * 5); + format %{ "revb_h_h_u $dst, $src\t#@bytes_reverse_unsigned_short" %} + + ins_encode %{ + __ revb_h_h_u(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_short(iRegINoSp dst, iRegIorL2I src) %{ + match(Set dst (ReverseBytesS src)); + + ins_cost(ALU_COST * 5); + format %{ "revb_h_h $dst, $src\t#@bytes_reverse_short" %} + + ins_encode %{ + __ revb_h_h(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// ============================================================================ +// MemBar Instruction + +instruct load_fence() %{ + match(LoadFence); + ins_cost(ALU_COST); + + format %{ "#@load_fence" %} + + ins_encode %{ + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + %} + ins_pipe(pipe_serial); +%} + +instruct membar_acquire() %{ + match(MemBarAcquire); + ins_cost(ALU_COST); + + format %{ "#@membar_acquire\n\t" + "fence ir iorw" %} + + ins_encode %{ + __ block_comment("membar_acquire"); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + %} + + ins_pipe(pipe_serial); +%} + +instruct membar_acquire_lock() %{ + match(MemBarAcquireLock); + ins_cost(0); + + format %{ "#@membar_acquire_lock (elided)" %} + + ins_encode %{ + __ block_comment("membar_acquire_lock (elided)"); + %} + + ins_pipe(pipe_serial); +%} + +instruct store_fence() %{ + match(StoreFence); + ins_cost(ALU_COST); + + format %{ "#@store_fence" %} + + ins_encode %{ + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + %} + ins_pipe(pipe_serial); +%} + +instruct membar_release() %{ + match(MemBarRelease); + ins_cost(ALU_COST); + + format %{ "#@membar_release\n\t" + "fence iorw ow" %} + + ins_encode %{ + __ block_comment("membar_release"); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + %} + ins_pipe(pipe_serial); +%} + +instruct membar_storestore() %{ + match(MemBarStoreStore); + match(StoreStoreFence); + ins_cost(ALU_COST); + + format %{ "MEMBAR-store-store\t#@membar_storestore" %} + + ins_encode %{ + __ membar(MacroAssembler::StoreStore); + %} + ins_pipe(pipe_serial); +%} + +instruct membar_release_lock() %{ + match(MemBarReleaseLock); + ins_cost(0); + + format %{ "#@membar_release_lock (elided)" %} + + ins_encode %{ + __ block_comment("membar_release_lock (elided)"); + %} + + ins_pipe(pipe_serial); +%} + +instruct membar_volatile() %{ + match(MemBarVolatile); + ins_cost(ALU_COST); + + format %{ "#@membar_volatile\n\t" + "fence iorw iorw"%} + + ins_encode %{ + __ block_comment("membar_volatile"); + __ membar(MacroAssembler::StoreLoad); + %} + + ins_pipe(pipe_serial); +%} + +// ============================================================================ +// Cast Instructions (Java-level type cast) + +instruct castX2P(iRegPNoSp dst, iRegL src) %{ + match(Set dst (CastX2P src)); + + ins_cost(ALU_COST); + format %{ "mv $dst, $src\t# long -> ptr, #@castX2P" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + if ($dst$$reg != $src$$reg) { + __ mv(as_Register($dst$$reg), as_Register($src$$reg)); + } + %} + + ins_pipe(ialu_reg); +%} + +instruct castP2X(iRegLNoSp dst, iRegP src) %{ + match(Set dst (CastP2X src)); + + ins_cost(ALU_COST); + format %{ "mv $dst, $src\t# ptr -> long, #@castP2X" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + if ($dst$$reg != $src$$reg) { + __ mv(as_Register($dst$$reg), as_Register($src$$reg)); + } + %} + + ins_pipe(ialu_reg); +%} + +instruct castPP(iRegPNoSp dst) +%{ + match(Set dst (CastPP dst)); + ins_cost(0); + + size(0); + format %{ "# castPP of $dst, #@castPP" %} + ins_encode(/* empty encoding */); + ins_pipe(pipe_class_empty); +%} + +instruct castLL(iRegL dst) +%{ + match(Set dst (CastLL dst)); + + size(0); + format %{ "# castLL of $dst, #@castLL" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +instruct castII(iRegI dst) +%{ + match(Set dst (CastII dst)); + + size(0); + format %{ "# castII of $dst, #@castII" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +instruct checkCastPP(iRegPNoSp dst) +%{ + match(Set dst (CheckCastPP dst)); + + size(0); + ins_cost(0); + format %{ "# checkcastPP of $dst, #@checkCastPP" %} + ins_encode(/* empty encoding */); + ins_pipe(pipe_class_empty); +%} + +instruct castFF(fRegF dst) +%{ + match(Set dst (CastFF dst)); + + size(0); + format %{ "# castFF of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +instruct castDD(fRegD dst) +%{ + match(Set dst (CastDD dst)); + + size(0); + format %{ "# castDD of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +instruct castVV(vReg dst) +%{ + match(Set dst (CastVV dst)); + + size(0); + format %{ "# castVV of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +// ============================================================================ +// Convert Instructions + +// int to bool +instruct convI2Bool(iRegINoSp dst, iRegI src) +%{ + match(Set dst (Conv2B src)); + + ins_cost(ALU_COST); + format %{ "snez $dst, $src\t#@convI2Bool" %} + + ins_encode %{ + __ snez(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// pointer to bool +instruct convP2Bool(iRegINoSp dst, iRegP src) +%{ + match(Set dst (Conv2B src)); + + ins_cost(ALU_COST); + format %{ "snez $dst, $src\t#@convP2Bool" %} + + ins_encode %{ + __ snez(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// int <-> long + +instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src) +%{ + match(Set dst (ConvI2L src)); + + ins_cost(ALU_COST); + format %{ "addw $dst, $src, zr\t#@convI2L_reg_reg" %} + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src$$reg), zr); + %} + ins_pipe(ialu_reg); +%} + +instruct convL2I_reg(iRegINoSp dst, iRegL src) %{ + match(Set dst (ConvL2I src)); + + ins_cost(ALU_COST); + format %{ "addw $dst, $src, zr\t#@convL2I_reg" %} + + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src$$reg), zr); + %} + + ins_pipe(ialu_reg); +%} + +// int to unsigned long (Zero-extend) +instruct convI2UL_reg_reg(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) +%{ + match(Set dst (AndL (ConvI2L src) mask)); + + ins_cost(ALU_COST * 2); + format %{ "zero_extend $dst, $src, 32\t# i2ul, #@convI2UL_reg_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ zero_extend(as_Register($dst$$reg), as_Register($src$$reg), 32); + %} + + ins_pipe(ialu_reg_shift); +%} + +// float <-> double + +instruct convF2D_reg(fRegD dst, fRegF src) %{ + match(Set dst (ConvF2D src)); + + ins_cost(XFER_COST); + format %{ "fcvt.d.s $dst, $src\t#@convF2D_reg" %} + + ins_encode %{ + __ fcvt_d_s(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_f2d); +%} + +instruct convD2F_reg(fRegF dst, fRegD src) %{ + match(Set dst (ConvD2F src)); + + ins_cost(XFER_COST); + format %{ "fcvt.s.d $dst, $src\t#@convD2F_reg" %} + + ins_encode %{ + __ fcvt_s_d(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_d2f); +%} + +// float <-> int + +instruct convF2I_reg_reg(iRegINoSp dst, fRegF src) %{ + match(Set dst (ConvF2I src)); + + ins_cost(XFER_COST); + format %{ "fcvt.w.s $dst, $src\t#@convF2I_reg_reg" %} + + ins_encode %{ + __ fcvt_w_s_safe($dst$$Register, $src$$FloatRegister); + %} + + ins_pipe(fp_f2i); +%} + +instruct convI2F_reg_reg(fRegF dst, iRegIorL2I src) %{ + match(Set dst (ConvI2F src)); + + ins_cost(XFER_COST); + format %{ "fcvt.s.w $dst, $src\t#@convI2F_reg_reg" %} + + ins_encode %{ + __ fcvt_s_w(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_i2f); +%} + +// float <-> long + +instruct convF2L_reg_reg(iRegLNoSp dst, fRegF src) %{ + match(Set dst (ConvF2L src)); + + ins_cost(XFER_COST); + format %{ "fcvt.l.s $dst, $src\t#@convF2L_reg_reg" %} + + ins_encode %{ + __ fcvt_l_s_safe($dst$$Register, $src$$FloatRegister); + %} + + ins_pipe(fp_f2l); +%} + +instruct convL2F_reg_reg(fRegF dst, iRegL src) %{ + match(Set dst (ConvL2F src)); + + ins_cost(XFER_COST); + format %{ "fcvt.s.l $dst, $src\t#@convL2F_reg_reg" %} + + ins_encode %{ + __ fcvt_s_l(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_l2f); +%} + +// double <-> int + +instruct convD2I_reg_reg(iRegINoSp dst, fRegD src) %{ + match(Set dst (ConvD2I src)); + + ins_cost(XFER_COST); + format %{ "fcvt.w.d $dst, $src\t#@convD2I_reg_reg" %} + + ins_encode %{ + __ fcvt_w_d_safe($dst$$Register, $src$$FloatRegister); + %} + + ins_pipe(fp_d2i); +%} + +instruct convI2D_reg_reg(fRegD dst, iRegIorL2I src) %{ + match(Set dst (ConvI2D src)); + + ins_cost(XFER_COST); + format %{ "fcvt.d.w $dst, $src\t#@convI2D_reg_reg" %} + + ins_encode %{ + __ fcvt_d_w(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_i2d); +%} + +// double <-> long + +instruct convD2L_reg_reg(iRegLNoSp dst, fRegD src) %{ + match(Set dst (ConvD2L src)); + + ins_cost(XFER_COST); + format %{ "fcvt.l.d $dst, $src\t#@convD2L_reg_reg" %} + + ins_encode %{ + __ fcvt_l_d_safe($dst$$Register, $src$$FloatRegister); + %} + + ins_pipe(fp_d2l); +%} + +instruct convL2D_reg_reg(fRegD dst, iRegL src) %{ + match(Set dst (ConvL2D src)); + + ins_cost(XFER_COST); + format %{ "fcvt.d.l $dst, $src\t#@convL2D_reg_reg" %} + + ins_encode %{ + __ fcvt_d_l(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_l2d); +%} + +// Convert oop into int for vectors alignment masking +instruct convP2I(iRegINoSp dst, iRegP src) %{ + match(Set dst (ConvL2I (CastP2X src))); + + ins_cost(ALU_COST * 2); + format %{ "zero_extend $dst, $src, 32\t# ptr -> int, #@convP2I" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ zero_extend($dst$$Register, $src$$Register, 32); + %} + + ins_pipe(ialu_reg); +%} + +// Convert compressed oop into int for vectors alignment masking +// in case of 32bit oops (heap < 4Gb). +instruct convN2I(iRegINoSp dst, iRegN src) +%{ + predicate(CompressedOops::shift() == 0); + match(Set dst (ConvL2I (CastP2X (DecodeN src)))); + + ins_cost(ALU_COST); + format %{ "mv $dst, $src\t# compressed ptr -> int, #@convN2I" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ mv($dst$$Register, $src$$Register); + %} + + ins_pipe(ialu_reg); +%} + +// Convert oop pointer into compressed form +instruct encodeHeapOop(iRegNNoSp dst, iRegP src) %{ + match(Set dst (EncodeP src)); + ins_cost(ALU_COST); + format %{ "encode_heap_oop $dst, $src\t#@encodeHeapOop" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ encode_heap_oop(d, s); + %} + ins_pipe(ialu_reg); +%} + +instruct decodeHeapOop(iRegPNoSp dst, iRegN src) %{ + predicate(n->bottom_type()->is_ptr()->ptr() != TypePtr::NotNull && + n->bottom_type()->is_ptr()->ptr() != TypePtr::Constant); + match(Set dst (DecodeN src)); + + ins_cost(0); + format %{ "decode_heap_oop $dst, $src\t#@decodeHeapOop" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ decode_heap_oop(d, s); + %} + ins_pipe(ialu_reg); +%} + +instruct decodeHeapOop_not_null(iRegPNoSp dst, iRegN src) %{ + predicate(n->bottom_type()->is_ptr()->ptr() == TypePtr::NotNull || + n->bottom_type()->is_ptr()->ptr() == TypePtr::Constant); + match(Set dst (DecodeN src)); + + ins_cost(0); + format %{ "decode_heap_oop_not_null $dst, $src\t#@decodeHeapOop_not_null" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ decode_heap_oop_not_null(d, s); + %} + ins_pipe(ialu_reg); +%} + +// Convert klass pointer into compressed form. +instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{ + match(Set dst (EncodePKlass src)); + + ins_cost(ALU_COST); + format %{ "encode_klass_not_null $dst, $src\t#@encodeKlass_not_null" %} + + ins_encode %{ + Register src_reg = as_Register($src$$reg); + Register dst_reg = as_Register($dst$$reg); + __ encode_klass_not_null(dst_reg, src_reg, t0); + %} + + ins_pipe(ialu_reg); +%} + +instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src, iRegPNoSp tmp) %{ + match(Set dst (DecodeNKlass src)); + + effect(TEMP tmp); + + ins_cost(ALU_COST); + format %{ "decode_klass_not_null $dst, $src\t#@decodeKlass_not_null" %} + + ins_encode %{ + Register src_reg = as_Register($src$$reg); + Register dst_reg = as_Register($dst$$reg); + Register tmp_reg = as_Register($tmp$$reg); + __ decode_klass_not_null(dst_reg, src_reg, tmp_reg); + %} + + ins_pipe(ialu_reg); +%} + +// stack <-> reg and reg <-> reg shuffles with no conversion + +instruct MoveF2I_stack_reg(iRegINoSp dst, stackSlotF src) %{ + + match(Set dst (MoveF2I src)); + + effect(DEF dst, USE src); + + ins_cost(LOAD_COST); + + format %{ "lw $dst, $src\t#@MoveF2I_stack_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ lw(as_Register($dst$$reg), Address(sp, $src$$disp)); + %} + + ins_pipe(iload_reg_reg); + +%} + +instruct MoveI2F_stack_reg(fRegF dst, stackSlotI src) %{ + + match(Set dst (MoveI2F src)); + + effect(DEF dst, USE src); + + ins_cost(LOAD_COST); + + format %{ "flw $dst, $src\t#@MoveI2F_stack_reg" %} + + ins_encode %{ + __ flw(as_FloatRegister($dst$$reg), Address(sp, $src$$disp)); + %} + + ins_pipe(pipe_class_memory); + +%} + +instruct MoveD2L_stack_reg(iRegLNoSp dst, stackSlotD src) %{ + + match(Set dst (MoveD2L src)); + + effect(DEF dst, USE src); + + ins_cost(LOAD_COST); + + format %{ "ld $dst, $src\t#@MoveD2L_stack_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ ld(as_Register($dst$$reg), Address(sp, $src$$disp)); + %} + + ins_pipe(iload_reg_reg); + +%} + +instruct MoveL2D_stack_reg(fRegD dst, stackSlotL src) %{ + + match(Set dst (MoveL2D src)); + + effect(DEF dst, USE src); + + ins_cost(LOAD_COST); + + format %{ "fld $dst, $src\t#@MoveL2D_stack_reg" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ fld(as_FloatRegister($dst$$reg), Address(sp, $src$$disp)); + %} + + ins_pipe(pipe_class_memory); + +%} + +instruct MoveF2I_reg_stack(stackSlotI dst, fRegF src) %{ + + match(Set dst (MoveF2I src)); + + effect(DEF dst, USE src); + + ins_cost(STORE_COST); + + format %{ "fsw $src, $dst\t#@MoveF2I_reg_stack" %} + + ins_encode %{ + __ fsw(as_FloatRegister($src$$reg), Address(sp, $dst$$disp)); + %} + + ins_pipe(pipe_class_memory); + +%} + +instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ + + match(Set dst (MoveI2F src)); + + effect(DEF dst, USE src); + + ins_cost(STORE_COST); + + format %{ "sw $src, $dst\t#@MoveI2F_reg_stack" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sw(as_Register($src$$reg), Address(sp, $dst$$disp)); + %} + + ins_pipe(istore_reg_reg); + +%} + +instruct MoveD2L_reg_stack(stackSlotL dst, fRegD src) %{ + + match(Set dst (MoveD2L src)); + + effect(DEF dst, USE src); + + ins_cost(STORE_COST); + + format %{ "fsd $dst, $src\t#@MoveD2L_reg_stack" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ fsd(as_FloatRegister($src$$reg), Address(sp, $dst$$disp)); + %} + + ins_pipe(pipe_class_memory); + +%} + +instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ + + match(Set dst (MoveL2D src)); + + effect(DEF dst, USE src); + + ins_cost(STORE_COST); + + format %{ "sd $src, $dst\t#@MoveL2D_reg_stack" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + __ sd(as_Register($src$$reg), Address(sp, $dst$$disp)); + %} + + ins_pipe(istore_reg_reg); + +%} + +instruct MoveF2I_reg_reg(iRegINoSp dst, fRegF src) %{ + + match(Set dst (MoveF2I src)); + + effect(DEF dst, USE src); + + ins_cost(XFER_COST); + + format %{ "fmv.x.w $dst, $src\t#@MoveL2D_reg_stack" %} + + ins_encode %{ + __ fmv_x_w(as_Register($dst$$reg), as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_f2i); + +%} + +instruct MoveI2F_reg_reg(fRegF dst, iRegI src) %{ + + match(Set dst (MoveI2F src)); + + effect(DEF dst, USE src); + + ins_cost(XFER_COST); + + format %{ "fmv.w.x $dst, $src\t#@MoveI2F_reg_reg" %} + + ins_encode %{ + __ fmv_w_x(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_i2f); + +%} + +instruct MoveD2L_reg_reg(iRegLNoSp dst, fRegD src) %{ + + match(Set dst (MoveD2L src)); + + effect(DEF dst, USE src); + + ins_cost(XFER_COST); + + format %{ "fmv.x.d $dst, $src\t#@MoveD2L_reg_reg" %} + + ins_encode %{ + __ fmv_x_d(as_Register($dst$$reg), as_FloatRegister($src$$reg)); + %} + + ins_pipe(fp_d2l); + +%} + +instruct MoveL2D_reg_reg(fRegD dst, iRegL src) %{ + + match(Set dst (MoveL2D src)); + + effect(DEF dst, USE src); + + ins_cost(XFER_COST); + + format %{ "fmv.d.x $dst, $src\t#@MoveD2L_reg_reg" %} + + ins_encode %{ + __ fmv_d_x(as_FloatRegister($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(fp_l2d); +%} + +// ============================================================================ +// Compare Instructions which set the result float comparisons in dest register. + +instruct cmpF3_reg_reg(iRegINoSp dst, fRegF op1, fRegF op2) +%{ + match(Set dst (CmpF3 op1 op2)); + + ins_cost(XFER_COST * 2 + BRANCH_COST + ALU_COST); + format %{ "flt.s $dst, $op2, $op1\t#@cmpF3_reg_reg\n\t" + "bgtz $dst, done\n\t" + "feq.s $dst, $op1, $op2\n\t" + "addi $dst, $dst, -1\t#@cmpF3_reg_reg" + %} + + ins_encode %{ + // we want -1 for unordered or less than, 0 for equal and 1 for greater than. + __ float_compare(as_Register($dst$$reg), as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), -1 /*unordered_result < 0*/); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpD3_reg_reg(iRegINoSp dst, fRegD op1, fRegD op2) +%{ + match(Set dst (CmpD3 op1 op2)); + + ins_cost(XFER_COST * 2 + BRANCH_COST + ALU_COST); + format %{ "flt.d $dst, $op2, $op1\t#@cmpD3_reg_reg\n\t" + "bgtz $dst, done\n\t" + "feq.d $dst, $op1, $op2\n\t" + "addi $dst, $dst, -1\t#@cmpD3_reg_reg" + %} + + ins_encode %{ + // we want -1 for unordered or less than, 0 for equal and 1 for greater than. + __ double_compare(as_Register($dst$$reg), as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), -1 /*unordered_result < 0*/); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpL3_reg_reg(iRegINoSp dst, iRegL op1, iRegL op2) +%{ + match(Set dst (CmpL3 op1 op2)); + + ins_cost(ALU_COST * 3 + BRANCH_COST); + format %{ "slt $dst, $op2, $op1\t#@cmpL3_reg_reg\n\t" + "bnez $dst, done\n\t" + "slt $dst, $op1, $op2\n\t" + "neg $dst, $dst\t#@cmpL3_reg_reg" + %} + ins_encode %{ + __ cmp_l2i(t0, as_Register($op1$$reg), as_Register($op2$$reg)); + __ mv(as_Register($dst$$reg), t0); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpLTMask_reg_reg(iRegINoSp dst, iRegI p, iRegI q) +%{ + match(Set dst (CmpLTMask p q)); + + ins_cost(2 * ALU_COST); + + format %{ "slt $dst, $p, $q\t#@cmpLTMask_reg_reg\n\t" + "subw $dst, zr, $dst\t#@cmpLTMask_reg_reg" + %} + + ins_encode %{ + __ slt(as_Register($dst$$reg), as_Register($p$$reg), as_Register($q$$reg)); + __ subw(as_Register($dst$$reg), zr, as_Register($dst$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct cmpLTMask_reg_zero(iRegINoSp dst, iRegIorL2I op, immI0 zero) +%{ + match(Set dst (CmpLTMask op zero)); + + ins_cost(ALU_COST); + + format %{ "sraiw $dst, $dst, 31\t#@cmpLTMask_reg_reg" %} + + ins_encode %{ + __ sraiw(as_Register($dst$$reg), as_Register($op$$reg), 31); + %} + + ins_pipe(ialu_reg_shift); +%} + + +// ============================================================================ +// Max and Min + +instruct minI_rReg(iRegINoSp dst, iRegI src1, iRegI src2) +%{ + match(Set dst (MinI src1 src2)); + + effect(DEF dst, USE src1, USE src2); + + ins_cost(BRANCH_COST + ALU_COST * 2); + format %{ + "ble $src1, $src2, Lsrc1.\t#@minI_rReg\n\t" + "mv $dst, $src2\n\t" + "j Ldone\n\t" + "bind Lsrc1\n\t" + "mv $dst, $src1\n\t" + "bind\t#@minI_rReg" + %} + + ins_encode %{ + Label Lsrc1, Ldone; + __ ble(as_Register($src1$$reg), as_Register($src2$$reg), Lsrc1); + __ mv(as_Register($dst$$reg), as_Register($src2$$reg)); + __ j(Ldone); + __ bind(Lsrc1); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct maxI_rReg(iRegINoSp dst, iRegI src1, iRegI src2) +%{ + match(Set dst (MaxI src1 src2)); + + effect(DEF dst, USE src1, USE src2); + + ins_cost(BRANCH_COST + ALU_COST * 2); + format %{ + "bge $src1, $src2, Lsrc1\t#@maxI_rReg\n\t" + "mv $dst, $src2\n\t" + "j Ldone\n\t" + "bind Lsrc1\n\t" + "mv $dst, $src1\n\t" + "bind\t#@maxI_rReg" + %} + + ins_encode %{ + Label Lsrc1, Ldone; + __ bge(as_Register($src1$$reg), as_Register($src2$$reg), Lsrc1); + __ mv(as_Register($dst$$reg), as_Register($src2$$reg)); + __ j(Ldone); + __ bind(Lsrc1); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + + %} + + ins_pipe(ialu_reg_reg); +%} + +// ============================================================================ +// Branch Instructions +// Direct Branch. +instruct branch(label lbl) +%{ + match(Goto); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "j $lbl\t#@branch" %} + + ins_encode(riscv_enc_j(lbl)); + + ins_pipe(pipe_branch); +%} + +// ============================================================================ +// Compare and Branch Instructions + +// Patterns for short (< 12KiB) variants + +// Compare flags and branch near instructions. +instruct cmpFlag_branch(cmpOpEqNe cmp, rFlagsReg cr, label lbl) %{ + match(If cmp cr); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $cr, zr, $lbl\t#@cmpFlag_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label)); + %} + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare signed int and branch near instructions +instruct cmpI_branch(cmpOp cmp, iRegI op1, iRegI op2, label lbl) +%{ + // Same match rule as `far_cmpI_branch'. + match(If cmp (CmpI op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpI_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpI_loop(cmpOp cmp, iRegI op1, iRegI op2, label lbl) +%{ + // Same match rule as `far_cmpI_loop'. + match(CountedLoopEnd cmp (CmpI op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpI_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare unsigned int and branch near instructions +instruct cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) +%{ + // Same match rule as `far_cmpU_branch'. + match(If cmp (CmpU op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpU_loop(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) +%{ + // Same match rule as `far_cmpU_loop'. + match(CountedLoopEnd cmp (CmpU op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare signed long and branch near instructions +instruct cmpL_branch(cmpOp cmp, iRegL op1, iRegL op2, label lbl) +%{ + // Same match rule as `far_cmpL_branch'. + match(If cmp (CmpL op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpL_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpL_loop(cmpOp cmp, iRegL op1, iRegL op2, label lbl) +%{ + // Same match rule as `far_cmpL_loop'. + match(CountedLoopEnd cmp (CmpL op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpL_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare unsigned long and branch near instructions +instruct cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) +%{ + // Same match rule as `far_cmpUL_branch'. + match(If cmp (CmpUL op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpUL_loop(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) +%{ + // Same match rule as `far_cmpUL_loop'. + match(CountedLoopEnd cmp (CmpUL op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare pointer and branch near instructions +instruct cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) +%{ + // Same match rule as `far_cmpP_branch'. + match(If cmp (CmpP op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpP_loop(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) +%{ + // Same match rule as `far_cmpP_loop'. + match(CountedLoopEnd cmp (CmpP op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare narrow pointer and branch near instructions +instruct cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) +%{ + // Same match rule as `far_cmpN_branch'. + match(If cmp (CmpN op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +instruct cmpN_loop(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) +%{ + // Same match rule as `far_cmpN_loop'. + match(CountedLoopEnd cmp (CmpN op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmp_branch); + ins_short_branch(1); +%} + +// Compare float and branch near instructions +instruct cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl) +%{ + // Same match rule as `far_cmpF_branch'. + match(If cmp (CmpF op1 op2)); + + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); + format %{ "float_b$cmp $op1, $op2 \t#@cmpF_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_class_compare); + ins_short_branch(1); +%} + +instruct cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl) +%{ + // Same match rule as `far_cmpF_loop'. + match(CountedLoopEnd cmp (CmpF op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); + format %{ "float_b$cmp $op1, $op2\t#@cmpF_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_class_compare); + ins_short_branch(1); +%} + +// Compare double and branch near instructions +instruct cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) +%{ + // Same match rule as `far_cmpD_branch'. + match(If cmp (CmpD op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); + format %{ "double_b$cmp $op1, $op2\t#@cmpD_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_class_compare); + ins_short_branch(1); +%} + +instruct cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) +%{ + // Same match rule as `far_cmpD_loop'. + match(CountedLoopEnd cmp (CmpD op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); + format %{ "double_b$cmp $op1, $op2\t#@cmpD_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_class_compare); + ins_short_branch(1); +%} + +// Compare signed int with zero and branch near instructions +instruct cmpI_reg_imm0_branch(cmpOp cmp, iRegI op1, immI0 zero, label lbl) +%{ + // Same match rule as `far_cmpI_reg_imm0_branch'. + match(If cmp (CmpI op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, zr, $lbl\t#@cmpI_reg_imm0_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpI_reg_imm0_loop(cmpOp cmp, iRegI op1, immI0 zero, label lbl) +%{ + // Same match rule as `far_cmpI_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpI op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpI_reg_imm0_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare unsigned int with zero and branch near instructions +instruct cmpUEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl) +%{ + // Same match rule as `far_cmpUEqNeLeGt_reg_imm0_branch'. + match(If cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpUEqNeLeGt_reg_imm0_branch" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpUEqNeLeGt_reg_imm0_loop(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl) +%{ + // Same match rule as `far_cmpUEqNeLeGt_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpUEqNeLeGt_reg_imm0_loop" %} + + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare signed long with zero and branch near instructions +instruct cmpL_reg_imm0_branch(cmpOp cmp, iRegL op1, immL0 zero, label lbl) +%{ + // Same match rule as `far_cmpL_reg_imm0_branch'. + match(If cmp (CmpL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpL_reg_imm0_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpL_reg_imm0_loop(cmpOp cmp, iRegL op1, immL0 zero, label lbl) +%{ + // Same match rule as `far_cmpL_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpL_reg_imm0_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare unsigned long with zero and branch near instructions +instruct cmpULEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl) +%{ + // Same match rule as `far_cmpULEqNeLeGt_reg_imm0_branch'. + match(If cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpULEqNeLeGt_reg_imm0_branch" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpULEqNeLeGt_reg_imm0_loop(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl) +%{ + // Same match rule as `far_cmpULEqNeLeGt_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpULEqNeLeGt_reg_imm0_loop" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare pointer with zero and branch near instructions +instruct cmpP_imm0_branch(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{ + // Same match rule as `far_cmpP_reg_imm0_branch'. + match(If cmp (CmpP op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpP_imm0_loop(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{ + // Same match rule as `far_cmpP_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpP op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare narrow pointer with zero and branch near instructions +instruct cmpN_imm0_branch(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{ + // Same match rule as `far_cmpN_reg_imm0_branch'. + match(If cmp (CmpN op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpN_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpN_imm0_loop(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{ + // Same match rule as `far_cmpN_reg_imm0_loop'. + match(CountedLoopEnd cmp (CmpN op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "b$cmp $op1, zr, $lbl\t#@cmpN_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Compare narrow pointer with pointer zero and branch near instructions +instruct cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{ + // Same match rule as `far_cmpP_narrowOop_imm0_branch'. + match(If cmp (CmpP (DecodeN op1) zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_narrowOop_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +instruct cmpP_narrowOop_imm0_loop(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{ + // Same match rule as `far_cmpP_narrowOop_imm0_loop'. + match(CountedLoopEnd cmp (CmpP (DecodeN op1) zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_narrowOop_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label)); + %} + + ins_pipe(pipe_cmpz_branch); + ins_short_branch(1); +%} + +// Patterns for far (20KiB) variants + +instruct far_cmpFlag_branch(cmpOp cmp, rFlagsReg cr, label lbl) %{ + match(If cmp cr); + effect(USE lbl); + + ins_cost(BRANCH_COST); + format %{ "far_b$cmp $cr, zr, L\t#@far_cmpFlag_branch"%} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +// Compare signed int and branch far instructions +instruct far_cmpI_branch(cmpOp cmp, iRegI op1, iRegI op2, label lbl) %{ + match(If cmp (CmpI op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + // the format instruction [far_b$cmp] here is be used as two insructions + // in macroassembler: b$not_cmp(op1, op2, done), j($lbl), bind(done) + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpI_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpI_loop(cmpOp cmp, iRegI op1, iRegI op2, label lbl) %{ + match(CountedLoopEnd cmp (CmpI op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpI_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) %{ + match(If cmp (CmpU op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpU_loop(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) %{ + match(CountedLoopEnd cmp (CmpU op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpL_branch(cmpOp cmp, iRegL op1, iRegL op2, label lbl) %{ + match(If cmp (CmpL op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpL_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpLloop(cmpOp cmp, iRegL op1, iRegL op2, label lbl) %{ + match(CountedLoopEnd cmp (CmpL op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpL_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) %{ + match(If cmp (CmpUL op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpUL_loop(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) %{ + match(CountedLoopEnd cmp (CmpUL op1 op2)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) +%{ + match(If cmp (CmpP op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpP_loop(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) +%{ + match(CountedLoopEnd cmp (CmpP op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) +%{ + match(If cmp (CmpN op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +instruct far_cmpN_loop(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) +%{ + match(CountedLoopEnd cmp (CmpN op1 op2)); + + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmp_branch); +%} + +// Float compare and branch instructions +instruct far_cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl) +%{ + match(If cmp (CmpF op1 op2)); + + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); + format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct far_cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl) +%{ + match(CountedLoopEnd cmp (CmpF op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); + format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_class_compare); +%} + +// Double compare and branch instructions +instruct far_cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) +%{ + match(If cmp (CmpD op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); + format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct far_cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) +%{ + match(CountedLoopEnd cmp (CmpD op1 op2)); + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); + format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct far_cmpI_reg_imm0_branch(cmpOp cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(If cmp (CmpI op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpI_reg_imm0_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpI_reg_imm0_loop(cmpOp cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpI op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpI_reg_imm0_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpUEqNeLeGt_imm0_branch(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(If cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpUEqNeLeGt_imm0_branch" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpUEqNeLeGt_reg_imm0_loop(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpUEqNeLeGt_reg_imm0_loop" %} + + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +// compare lt/ge unsigned instructs has no short instruct with same match +instruct far_cmpULtGe_reg_imm0_branch(cmpOpULtGe cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(If cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "j $lbl if $cmp == ge\t#@far_cmpULtGe_reg_imm0_branch" %} + + ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl)); + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpULtGe_reg_imm0_loop(cmpOpULtGe cmp, iRegI op1, immI0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpU op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "j $lbl if $cmp == ge\t#@far_cmpULtGe_reg_imm0_loop" %} + + ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl)); + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpL_reg_imm0_branch(cmpOp cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(If cmp (CmpL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpL_reg_imm0_branch" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpL_reg_imm0_loop(cmpOp cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpL_reg_imm0_loop" %} + + ins_encode %{ + __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpULEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(If cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpULEqNeLeGt_reg_imm0_branch" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpULEqNeLeGt_reg_imm0_loop(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpULEqNeLeGt_reg_imm0_loop" %} + + ins_encode %{ + __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +// compare lt/ge unsigned instructs has no short instruct with same match +instruct far_cmpULLtGe_reg_imm0_branch(cmpOpULtGe cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(If cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "j $lbl if $cmp == ge\t#@far_cmpULLtGe_reg_imm0_branch" %} + + ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl)); + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpULLtGe_reg_imm0_loop(cmpOpULtGe cmp, iRegL op1, immL0 zero, label lbl) +%{ + match(CountedLoopEnd cmp (CmpUL op1 zero)); + + effect(USE op1, USE lbl); + + ins_cost(BRANCH_COST); + + format %{ "j $lbl if $cmp == ge\t#@far_cmpULLtGe_reg_imm0_loop" %} + + ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl)); + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpP_imm0_branch(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{ + match(If cmp (CmpP op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpP_imm0_loop(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{ + match(CountedLoopEnd cmp (CmpP op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpN_imm0_branch(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{ + match(If cmp (CmpN op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpN_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpN_imm0_loop(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{ + match(CountedLoopEnd cmp (CmpN op1 zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpN_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{ + match(If cmp (CmpP (DecodeN op1) zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_narrowOop_imm0_branch" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +instruct far_cmpP_narrowOop_imm0_loop(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{ + match(CountedLoopEnd cmp (CmpP (DecodeN op1) zero)); + effect(USE lbl); + + ins_cost(BRANCH_COST * 2); + format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_narrowOop_imm0_loop" %} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true); + %} + + ins_pipe(pipe_cmpz_branch); +%} + +// ============================================================================ +// Conditional Move Instructions +instruct cmovI_cmpI(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOp cop) %{ + match(Set dst (CMoveI (Binary cop (CmpI op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "bneg$cop $op1, $op2, skip\t#@cmovI_cmpI\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop) %{ + match(Set dst (CMoveI (Binary cop (CmpU op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "bneg$cop $op1, $op2, skip\t#@cmovI_cmpU\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmovI_cmpL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOp cop) %{ + match(Set dst (CMoveI (Binary cop (CmpL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "bneg$cop $op1, $op2, skip\t#@cmovI_cmpL\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmovL_cmpL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOp cop) %{ + match(Set dst (CMoveL (Binary cop (CmpL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "bneg$cop $op1, $op2, skip\t#@cmovL_cmpL\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop) %{ + match(Set dst (CMoveL (Binary cop (CmpUL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "bneg$cop $op1, $op2, skip\t#@cmovL_cmpUL\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) %{ + match(Set dst (CMoveI (Binary cop (CmpUL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + format %{ + "bneg$cop $op1, $op2\t#@cmovI_cmpUL\n\t" + "mv $dst, $src\n\t" + "skip:" + %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(pipe_slow); +%} + + +// ============================================================================ +// Procedure Call/Return Instructions + +// Call Java Static Instruction +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallStaticJavaDirect(method meth) +%{ + match(CallStaticJava); + + effect(USE meth); + + ins_cost(BRANCH_COST); + + format %{ "CALL,static $meth\t#@CallStaticJavaDirect" %} + + ins_encode(riscv_enc_java_static_call(meth), + riscv_enc_call_epilog); + + ins_pipe(pipe_class_call); + ins_alignment(4); +%} + +// TO HERE + +// Call Java Dynamic Instruction +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallDynamicJavaDirect(method meth, rFlagsReg cr) +%{ + match(CallDynamicJava); + + effect(USE meth, KILL cr); + + ins_cost(BRANCH_COST + ALU_COST * 6); + + format %{ "CALL,dynamic $meth\t#@CallDynamicJavaDirect" %} + + ins_encode(riscv_enc_java_dynamic_call(meth), + riscv_enc_call_epilog); + + ins_pipe(pipe_class_call); + ins_alignment(4); +%} + +// Call Runtime Instruction + +instruct CallRuntimeDirect(method meth, rFlagsReg cr) +%{ + match(CallRuntime); + + effect(USE meth, KILL cr); + + ins_cost(BRANCH_COST); + + format %{ "CALL, runtime $meth\t#@CallRuntimeDirect" %} + + ins_encode(riscv_enc_java_to_runtime(meth)); + + ins_pipe(pipe_class_call); +%} + +// Call Runtime Instruction + +instruct CallLeafDirect(method meth, rFlagsReg cr) +%{ + match(CallLeaf); + + effect(USE meth, KILL cr); + + ins_cost(BRANCH_COST); + + format %{ "CALL, runtime leaf $meth\t#@CallLeafDirect" %} + + ins_encode(riscv_enc_java_to_runtime(meth)); + + ins_pipe(pipe_class_call); +%} + +// Call Runtime Instruction + +instruct CallLeafNoFPDirect(method meth, rFlagsReg cr) +%{ + match(CallLeafNoFP); + + effect(USE meth, KILL cr); + + ins_cost(BRANCH_COST); + + format %{ "CALL, runtime leaf nofp $meth\t#@CallLeafNoFPDirect" %} + + ins_encode(riscv_enc_java_to_runtime(meth)); + + ins_pipe(pipe_class_call); +%} + +// ============================================================================ +// Partial Subtype Check +// +// superklass array for an instance of the superklass. Set a hidden +// internal cache on a hit (cache is checked with exposed code in +// gen_subtype_check()). Return zero for a hit. The encoding +// ALSO sets flags. + +instruct partialSubtypeCheck(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tmp, rFlagsReg cr) +%{ + match(Set result (PartialSubtypeCheck sub super)); + effect(KILL tmp, KILL cr); + + ins_cost(2 * STORE_COST + 3 * LOAD_COST + 4 * ALU_COST + BRANCH_COST * 4); + format %{ "partialSubtypeCheck $result, $sub, $super\t#@partialSubtypeCheck" %} + + ins_encode(riscv_enc_partial_subtype_check(sub, super, tmp, result)); + + opcode(0x1); // Force zero of result reg on hit + + ins_pipe(pipe_class_memory); +%} + +instruct partialSubtypeCheckVsZero(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tmp, + immP0 zero, rFlagsReg cr) +%{ + match(Set cr (CmpP (PartialSubtypeCheck sub super) zero)); + effect(KILL tmp, KILL result); + + ins_cost(2 * STORE_COST + 3 * LOAD_COST + 4 * ALU_COST + BRANCH_COST * 4); + format %{ "partialSubtypeCheck $result, $sub, $super == 0\t#@partialSubtypeCheckVsZero" %} + + ins_encode(riscv_enc_partial_subtype_check(sub, super, tmp, result)); + + opcode(0x0); // Don't zero result reg on hit + + ins_pipe(pipe_class_memory); +%} + +instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareU" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, + StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareL" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, + StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{"String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareUL" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, + StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, + rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareLU" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, + StrIntrinsicNode::LU); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexofUU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, + iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + $tmp5$$Register, $tmp6$$Register, + $result$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexofLL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, + iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL)" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + $tmp5$$Register, $tmp6$$Register, + $result$$Register, StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexofUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, + iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL)" %} + + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + $tmp5$$Register, $tmp6$$Register, + $result$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexof_conUU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, + immI_le_4 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU)" %} + + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + __ string_indexof_linearscan($str1$$Register, $str2$$Register, + $cnt1$$Register, zr, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + icnt2, $result$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexof_conLL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, + immI_le_4 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LL)" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + __ string_indexof_linearscan($str1$$Register, $str2$$Register, + $cnt1$$Register, zr, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + icnt2, $result$$Register, StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_indexof_conUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, + immI_1 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UL)" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + __ string_indexof_linearscan($str1$$Register, $str2$$Register, + $cnt1$$Register, zr, + $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, + icnt2, $result$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct stringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); + effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + + format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result" %} + ins_encode %{ + __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, + $result$$Register, $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, false /* isU */); + %} + ins_pipe(pipe_class_memory); +%} + + +instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); + effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + + format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result" %} + ins_encode %{ + __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, + $result$$Register, $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, true /* isL */); + %} + ins_pipe(pipe_class_memory); +%} + +// clearing of an array +instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy) +%{ + predicate(!UseRVV); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL cnt, USE_KILL base); + + ins_cost(4 * DEFAULT_COST); + format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %} + + ins_encode %{ + address tpc = __ zero_words($base$$Register, $cnt$$Register); + if (tpc == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + %} + + ins_pipe(pipe_class_memory); +%} + +instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr) +%{ + predicate(!UseRVV && (uint64_t)n->in(2)->get_long() + < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL base, KILL cr); + + ins_cost(4 * DEFAULT_COST); + format %{ "ClearArray $cnt, $base\t#@clearArray_imm_reg" %} + + ins_encode %{ + __ zero_words($base$$Register, (uint64_t)$cnt$$constant); + %} + + ins_pipe(pipe_class_memory); +%} + +instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + + format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsL" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_equals($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, 1); + %} + ins_pipe(pipe_class_memory); +%} + +instruct string_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, rFlagsReg cr) +%{ + predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + + format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_equals($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, 2); + %} + ins_pipe(pipe_class_memory); +%} + +instruct array_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, + iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, + iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) +%{ + predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); + + format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsB // KILL $tmp5" %} + ins_encode %{ + __ arrays_equals($ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, + $result$$Register, $tmp5$$Register, 1); + %} + ins_pipe(pipe_class_memory); +%} + +instruct array_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, + iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, + iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) +%{ + predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); + + format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsC // KILL $tmp5" %} + ins_encode %{ + __ arrays_equals($ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, + $result$$Register, $tmp5$$Register, 2); + %} + ins_pipe(pipe_class_memory); +%} + +// ============================================================================ +// Safepoint Instructions + +instruct safePoint(iRegP poll) +%{ + match(SafePoint poll); + + ins_cost(2 * LOAD_COST); + format %{ + "lwu zr, [$poll]\t# Safepoint: poll for GC, #@safePoint" + %} + ins_encode %{ + __ read_polling_page(as_Register($poll$$reg), 0, relocInfo::poll_type); + %} + ins_pipe(pipe_serial); // ins_pipe(iload_reg_mem); +%} + +// ============================================================================ +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(javaThread_RegP dst) +%{ + match(Set dst (ThreadLocal)); + + ins_cost(0); + + format %{ " -- \t// $dst=Thread::current(), empty, #@tlsLoadP" %} + + size(0); + + ins_encode( /*empty*/ ); + + ins_pipe(pipe_class_empty); +%} + +// inlined locking and unlocking +// using t1 as the 'flag' register to bridge the BoolNode producers and consumers +instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2) +%{ + match(Set cr (FastLock object box)); + effect(TEMP tmp1, TEMP tmp2); + + ins_cost(LOAD_COST * 2 + STORE_COST * 3 + ALU_COST * 6 + BRANCH_COST * 3); + format %{ "fastlock $object,$box\t! kills $tmp1,$tmp2, #@cmpFastLock" %} + + ins_encode(riscv_enc_fast_lock(object, box, tmp1, tmp2)); + + ins_pipe(pipe_serial); +%} + +// using t1 as the 'flag' register to bridge the BoolNode producers and consumers +instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2) +%{ + match(Set cr (FastUnlock object box)); + effect(TEMP tmp1, TEMP tmp2); + + ins_cost(LOAD_COST * 2 + STORE_COST + ALU_COST * 2 + BRANCH_COST * 4); + format %{ "fastunlock $object,$box\t! kills $tmp1, $tmp2, #@cmpFastUnlock" %} + + ins_encode(riscv_enc_fast_unlock(object, box, tmp1, tmp2)); + + ins_pipe(pipe_serial); +%} + +// Tail Call; Jump from runtime stub to Java code. +// Also known as an 'interprocedural jump'. +// Target of jump will eventually return to caller. +// TailJump below removes the return address. +instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_oop) +%{ + match(TailCall jump_target method_oop); + + ins_cost(BRANCH_COST); + + format %{ "jalr $jump_target\t# $method_oop holds method oop, #@TailCalljmpInd." %} + + ins_encode(riscv_enc_tail_call(jump_target)); + + ins_pipe(pipe_class_call); +%} + +instruct TailjmpInd(iRegPNoSp jump_target, iRegP_R10 ex_oop) +%{ + match(TailJump jump_target ex_oop); + + ins_cost(ALU_COST + BRANCH_COST); + + format %{ "jalr $jump_target\t# $ex_oop holds exception oop, #@TailjmpInd." %} + + ins_encode(riscv_enc_tail_jmp(jump_target)); + + ins_pipe(pipe_class_call); +%} + +// Create exception oop: created by stack-crawling runtime code. +// Created exception is now available to this handler, and is setup +// just prior to jumping to this handler. No code emitted. +instruct CreateException(iRegP_R10 ex_oop) +%{ + match(Set ex_oop (CreateEx)); + + ins_cost(0); + format %{ " -- \t// exception oop; no code emitted, #@CreateException" %} + + size(0); + + ins_encode( /*empty*/ ); + + ins_pipe(pipe_class_empty); +%} + +// Rethrow exception: The exception oop will come in the first +// argument position. Then JUMP (not call) to the rethrow stub code. +instruct RethrowException() +%{ + match(Rethrow); + + ins_cost(BRANCH_COST); + + format %{ "j rethrow_stub\t#@RethrowException" %} + + ins_encode(riscv_enc_rethrow()); + + ins_pipe(pipe_class_call); +%} + +// Return Instruction +// epilog node loads ret address into ra as part of frame pop +instruct Ret() +%{ + match(Return); + + ins_cost(BRANCH_COST); + format %{ "ret\t// return register, #@Ret" %} + + ins_encode(riscv_enc_ret()); + + ins_pipe(pipe_branch); +%} + +// Die now. +instruct ShouldNotReachHere() %{ + match(Halt); + + ins_cost(BRANCH_COST); + + format %{ "#@ShouldNotReachHere" %} + + ins_encode %{ + Assembler::CompressibleRegion cr(&_masm); + if (is_reachable()) { + __ halt(); + } + %} + + ins_pipe(pipe_class_default); +%} + + +//----------PEEPHOLE RULES----------------------------------------------------- +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. +// +// peepmatch ( root_instr_name [preceding_instruction]* ); +// +// peepconstraint %{ +// (instruction_number.operand_name relational_op instruction_number.operand_name +// [, ...] ); +// // instruction numbers are zero-based using left to right order in peepmatch +// +// peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); +// // provide an instruction_number.operand_name for each operand that appears +// // in the replacement instruction's match rule +// +// ---------VM FLAGS--------------------------------------------------------- +// +// All peephole optimizations can be turned off using -XX:-OptoPeephole +// +// Each peephole rule is given an identifying number starting with zero and +// increasing by one in the order seen by the parser. An individual peephole +// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# +// on the command-line. +// +// ---------CURRENT LIMITATIONS---------------------------------------------- +// +// Only match adjacent instructions in same basic block +// Only equality constraints +// Only constraints between operands, not (0.dest_reg == RAX_enc) +// Only one replacement instruction +// +//----------SMARTSPILL RULES--------------------------------------------------- +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. + +// Local Variables: +// mode: c++ +// End: diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad new file mode 100644 index 0000000000000000000000000000000000000000..bbebe13f0a8385a2b25da26b086becb1086d51c7 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv_b.ad @@ -0,0 +1,527 @@ +// +// Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +// RISCV Bit-Manipulation Extension Architecture Description File + +instruct rorI_imm_b(iRegINoSp dst, iRegI src, immI shift) %{ + predicate(UseZbb); + match(Set dst (RotateRight src shift)); + + format %{ "roriw $dst, $src, ($shift & 0x1f)\t#@rorI_imm_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ roriw(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x1f); + %} + + ins_pipe(ialu_reg_shift); +%} + +instruct rorL_imm_b(iRegLNoSp dst, iRegL src, immI shift) %{ + predicate(UseZbb); + match(Set dst (RotateRight src shift)); + + format %{ "rori $dst, $src, ($shift & 0x3f)\t#@rorL_imm_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ rori(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x3f); + %} + + ins_pipe(ialu_reg_shift); +%} + +instruct rorI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ + predicate(UseZbb); + match(Set dst (RotateRight src shift)); + + format %{ "rorw $dst, $src, $shift\t#@rorI_reg_b" %} + ins_cost(ALU_COST); + ins_encode %{ + __ rorw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct rorL_reg_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ + predicate(UseZbb); + match(Set dst (RotateRight src shift)); + + format %{ "ror $dst, $src, $shift\t#@rorL_reg_b" %} + ins_cost(ALU_COST); + ins_encode %{ + __ ror(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct rolI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ + predicate(UseZbb); + match(Set dst (RotateLeft src shift)); + + format %{ "rolw $dst, $src, $shift\t#@rolI_reg_b" %} + ins_cost(ALU_COST); + ins_encode %{ + __ rolw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct rolL_reg_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ + predicate(UseZbb); + match(Set dst (RotateLeft src shift)); + + format %{ "rol $dst, $src, $shift\t#@rolL_reg_b" %} + ins_cost(ALU_COST); + ins_encode %{ + __ rol(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); + %} + ins_pipe(ialu_reg_reg); +%} + +// Convert oop into int for vectors alignment masking +instruct convP2I_b(iRegINoSp dst, iRegP src) %{ + predicate(UseZba); + match(Set dst (ConvL2I (CastP2X src))); + + format %{ "zext.w $dst, $src\t# ptr -> int @convP2I_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ zext_w(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// byte to int +instruct convB2I_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_24 lshift, immI_24 rshift) %{ + predicate(UseZbb); + match(Set dst (RShiftI (LShiftI src lshift) rshift)); + + format %{ "sext.b $dst, $src\t# b2i, #@convB2I_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ sext_b(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// int to short +instruct convI2S_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_16 lshift, immI_16 rshift) %{ + predicate(UseZbb); + match(Set dst (RShiftI (LShiftI src lshift) rshift)); + + format %{ "sext.h $dst, $src\t# i2s, #@convI2S_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ sext_h(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// short to unsigned int +instruct convS2UI_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_16bits mask) %{ + predicate(UseZbb); + match(Set dst (AndI src mask)); + + format %{ "zext.h $dst, $src\t# s2ui, #@convS2UI_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ zext_h(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// int to unsigned long (zero extend) +instruct convI2UL_reg_reg_b(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ + predicate(UseZba); + match(Set dst (AndL (ConvI2L src) mask)); + + format %{ "zext.w $dst, $src\t# i2ul, #@convI2UL_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ zext_w(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg_shift); +%} + +// BSWAP instructions +instruct bytes_reverse_int_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UseZbb); + match(Set dst (ReverseBytesI src)); + + ins_cost(ALU_COST * 2); + format %{ "revb_w_w $dst, $src\t#@bytes_reverse_int_b" %} + + ins_encode %{ + __ revb_w_w(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_long_b(iRegLNoSp dst, iRegL src) %{ + predicate(UseZbb); + match(Set dst (ReverseBytesL src)); + + ins_cost(ALU_COST); + format %{ "rev8 $dst, $src\t#@bytes_reverse_long_b" %} + + ins_encode %{ + __ rev8(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_unsigned_short_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UseZbb); + match(Set dst (ReverseBytesUS src)); + + ins_cost(ALU_COST * 2); + format %{ "revb_h_h_u $dst, $src\t#@bytes_reverse_unsigned_short_b" %} + + ins_encode %{ + __ revb_h_h_u(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct bytes_reverse_short_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UseZbb); + match(Set dst (ReverseBytesS src)); + + ins_cost(ALU_COST * 2); + format %{ "revb_h_h $dst, $src\t#@bytes_reverse_short_b" %} + + ins_encode %{ + __ revb_h_h(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Shift Add Pointer +instruct shaddP_reg_reg_b(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale imm) %{ + predicate(UseZba); + match(Set dst (AddP src1 (LShiftL src2 imm))); + + ins_cost(ALU_COST); + format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), + as_Register($src2$$reg), + as_Register($src1$$reg), + t0, + $imm$$constant); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct shaddP_reg_reg_ext_b(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale imm) %{ + predicate(UseZba); + match(Set dst (AddP src1 (LShiftL (ConvI2L src2) imm))); + + ins_cost(ALU_COST); + format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_ext_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), + as_Register($src2$$reg), + as_Register($src1$$reg), + t0, + $imm$$constant); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Shift Add Long +instruct shaddL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immIScale imm) %{ + predicate(UseZba); + match(Set dst (AddL src1 (LShiftL src2 imm))); + + ins_cost(ALU_COST); + format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), + as_Register($src2$$reg), + as_Register($src1$$reg), + t0, + $imm$$constant); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct shaddL_reg_reg_ext_b(iRegLNoSp dst, iRegL src1, iRegI src2, immIScale imm) %{ + predicate(UseZba); + match(Set dst (AddL src1 (LShiftL (ConvI2L src2) imm))); + + ins_cost(ALU_COST); + format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_ext_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), + as_Register($src2$$reg), + as_Register($src1$$reg), + t0, + $imm$$constant); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Zeros Count instructions +instruct countLeadingZerosI_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UseZbb); + match(Set dst (CountLeadingZerosI src)); + + ins_cost(ALU_COST); + format %{ "clzw $dst, $src\t#@countLeadingZerosI_b" %} + + ins_encode %{ + __ clzw(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct countLeadingZerosL_b(iRegINoSp dst, iRegL src) %{ + predicate(UseZbb); + match(Set dst (CountLeadingZerosL src)); + + ins_cost(ALU_COST); + format %{ "clz $dst, $src\t#@countLeadingZerosL_b" %} + + ins_encode %{ + __ clz(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct countTrailingZerosI_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UseZbb); + match(Set dst (CountTrailingZerosI src)); + + ins_cost(ALU_COST); + format %{ "ctzw $dst, $src\t#@countTrailingZerosI_b" %} + + ins_encode %{ + __ ctzw(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +instruct countTrailingZerosL_b(iRegINoSp dst, iRegL src) %{ + predicate(UseZbb); + match(Set dst (CountTrailingZerosL src)); + + ins_cost(ALU_COST); + format %{ "ctz $dst, $src\t#@countTrailingZerosL_b" %} + + ins_encode %{ + __ ctz(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Population Count instructions +instruct popCountI_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + ins_cost(ALU_COST); + format %{ "cpopw $dst, $src\t#@popCountI_b" %} + + ins_encode %{ + __ cpopw(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Note: Long/bitCount(long) returns an int. +instruct popCountL_b(iRegINoSp dst, iRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + ins_cost(ALU_COST); + format %{ "cpop $dst, $src\t#@popCountL_b" %} + + ins_encode %{ + __ cpop(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// Max and Min +instruct minI_reg_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ + predicate(UseZbb); + match(Set dst (MinI src1 src2)); + + ins_cost(ALU_COST); + format %{ "min $dst, $src1, $src2\t#@minI_reg_b" %} + + ins_encode %{ + __ min(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct maxI_reg_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ + predicate(UseZbb); + match(Set dst (MaxI src1 src2)); + + ins_cost(ALU_COST); + format %{ "max $dst, $src1, $src2\t#@maxI_reg_b" %} + + ins_encode %{ + __ max(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Abs +instruct absI_reg_b(iRegINoSp dst, iRegI src) %{ + predicate(UseZbb); + match(Set dst (AbsI src)); + + ins_cost(ALU_COST * 2); + format %{ + "negw t0, $src\n\t" + "max $dst, $src, t0\t#@absI_reg_b" + %} + + ins_encode %{ + __ negw(t0, as_Register($src$$reg)); + __ max(as_Register($dst$$reg), as_Register($src$$reg), t0); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct absL_reg_b(iRegLNoSp dst, iRegL src) %{ + predicate(UseZbb); + match(Set dst (AbsL src)); + + ins_cost(ALU_COST * 2); + format %{ + "neg t0, $src\n\t" + "max $dst, $src, t0\t#@absL_reg_b" + %} + + ins_encode %{ + __ neg(t0, as_Register($src$$reg)); + __ max(as_Register($dst$$reg), as_Register($src$$reg), t0); + %} + + ins_pipe(ialu_reg); +%} + +// And Not +instruct andnI_reg_reg_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ + predicate(UseZbb); + match(Set dst (AndI src1 (XorI src2 m1))); + + ins_cost(ALU_COST); + format %{ "andn $dst, $src1, $src2\t#@andnI_reg_reg_b" %} + + ins_encode %{ + __ andn(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct andnL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ + predicate(UseZbb); + match(Set dst (AndL src1 (XorL src2 m1))); + + ins_cost(ALU_COST); + format %{ "andn $dst, $src1, $src2\t#@andnL_reg_reg_b" %} + + ins_encode %{ + __ andn(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Or Not +instruct ornI_reg_reg_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ + predicate(UseZbb); + match(Set dst (OrI src1 (XorI src2 m1))); + + ins_cost(ALU_COST); + format %{ "orn $dst, $src1, $src2\t#@ornI_reg_reg_b" %} + + ins_encode %{ + __ orn(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} + +instruct ornL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ + predicate(UseZbb); + match(Set dst (OrL src1 (XorL src2 m1))); + + ins_cost(ALU_COST); + format %{ "orn $dst, $src1, $src2\t#@ornL_reg_reg_b" %} + + ins_encode %{ + __ orn(as_Register($dst$$reg), + as_Register($src1$$reg), + as_Register($src2$$reg)); + %} + + ins_pipe(ialu_reg_reg); +%} \ No newline at end of file diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad new file mode 100644 index 0000000000000000000000000000000000000000..3828e096b21b5f00bd4ec68234756cb2bd5aced4 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -0,0 +1,2065 @@ +// +// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +// RISCV Vector Extension Architecture Description File + +opclass vmemA(indirect); + +source_hpp %{ + bool op_vec_supported(int opcode); +%} + +source %{ + + static void loadStore(C2_MacroAssembler masm, bool is_store, + VectorRegister reg, BasicType bt, Register base) { + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + masm.vsetvli(t0, x0, sew); + if (is_store) { + masm.vsex_v(reg, base, sew); + } else { + masm.vlex_v(reg, base, sew); + } + } + + bool op_vec_supported(int opcode) { + switch (opcode) { + // No multiply reduction instructions + case Op_MulReductionVD: + case Op_MulReductionVF: + case Op_MulReductionVI: + case Op_MulReductionVL: + // Others + case Op_Extract: + case Op_ExtractB: + case Op_ExtractC: + case Op_ExtractD: + case Op_ExtractF: + case Op_ExtractI: + case Op_ExtractL: + case Op_ExtractS: + case Op_ExtractUB: + // Vector API specific + case Op_AndReductionV: + case Op_OrReductionV: + case Op_XorReductionV: + case Op_LoadVectorGather: + case Op_StoreVectorScatter: + case Op_VectorBlend: + case Op_VectorCast: + case Op_VectorCastB2X: + case Op_VectorCastD2X: + case Op_VectorCastF2X: + case Op_VectorCastI2X: + case Op_VectorCastL2X: + case Op_VectorCastS2X: + case Op_VectorInsert: + case Op_VectorLoadConst: + case Op_VectorLoadMask: + case Op_VectorLoadShuffle: + case Op_VectorMaskCmp: + case Op_VectorRearrange: + case Op_VectorReinterpret: + case Op_VectorStoreMask: + case Op_VectorTest: + return false; + default: + return UseRVV; + } + } + +%} + +definitions %{ + int_def VEC_COST (200, 200); +%} + +// All VEC instructions + +// vector load/store +instruct loadV(vReg dst, vmemA mem) %{ + match(Set dst (LoadVector mem)); + ins_cost(VEC_COST); + format %{ "vle $dst, $mem\t#@loadV" %} + ins_encode %{ + VectorRegister dst_reg = as_VectorRegister($dst$$reg); + loadStore(C2_MacroAssembler(&cbuf), false, dst_reg, + Matcher::vector_element_basic_type(this), as_Register($mem$$base)); + %} + ins_pipe(pipe_slow); +%} + +instruct storeV(vReg src, vmemA mem) %{ + match(Set mem (StoreVector mem src)); + ins_cost(VEC_COST); + format %{ "vse $src, $mem\t#@storeV" %} + ins_encode %{ + VectorRegister src_reg = as_VectorRegister($src$$reg); + loadStore(C2_MacroAssembler(&cbuf), true, src_reg, + Matcher::vector_element_basic_type(this, $src), as_Register($mem$$base)); + %} + ins_pipe(pipe_slow); +%} + +// vector abs + +instruct vabsB(vReg dst, vReg src, vReg tmp) %{ + match(Set dst (AbsVB src)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vrsub.vi $tmp, 0, $src\t#@vabsB\n\t" + "vmax.vv $dst, $tmp, $src" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); + __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vabsS(vReg dst, vReg src, vReg tmp) %{ + match(Set dst (AbsVS src)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vrsub.vi $tmp, 0, $src\t#@vabsS\n\t" + "vmax.vv $dst, $tmp, $src" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); + __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vabsI(vReg dst, vReg src, vReg tmp) %{ + match(Set dst (AbsVI src)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vrsub.vi $tmp, 0, $src\t#@vabsI\n\t" + "vmax.vv $dst, $tmp, $src" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); + __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vabsL(vReg dst, vReg src, vReg tmp) %{ + match(Set dst (AbsVL src)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vrsub.vi $tmp, 0, $src\t#@vabsL\n\t" + "vmax.vv $dst, $tmp, $src" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); + __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vabsF(vReg dst, vReg src) %{ + match(Set dst (AbsVF src)); + ins_cost(VEC_COST); + format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vabsD(vReg dst, vReg src) %{ + match(Set dst (AbsVD src)); + ins_cost(VEC_COST); + format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector add + +instruct vaddB(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVB src1 src2)); + ins_cost(VEC_COST); + format %{ "vadd.vv $dst, $src1, $src2\t#@vaddB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vaddS(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVS src1 src2)); + ins_cost(VEC_COST); + format %{ "vadd.vv $dst, $src1, $src2\t#@vaddS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vaddI(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVI src1 src2)); + ins_cost(VEC_COST); + format %{ "vadd.vv $dst, $src1, $src2\t#@vaddI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vaddL(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVL src1 src2)); + ins_cost(VEC_COST); + format %{ "vadd.vv $dst, $src1, $src2\t#@vaddL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vaddF(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVF src1 src2)); + ins_cost(VEC_COST); + format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vaddD(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AddVD src1 src2)); + ins_cost(VEC_COST); + format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector and + +instruct vand(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (AndV src1 src2)); + ins_cost(VEC_COST); + format %{ "vand.vv $dst, $src1, $src2\t#@vand" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vand_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector or + +instruct vor(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (OrV src1 src2)); + ins_cost(VEC_COST); + format %{ "vor.vv $dst, $src1, $src2\t#@vor" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vor_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector xor + +instruct vxor(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (XorV src1 src2)); + ins_cost(VEC_COST); + format %{ "vxor.vv $dst, $src1, $src2\t#@vxor" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vxor_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector float div + +instruct vdivF(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (DivVF src1 src2)); + ins_cost(VEC_COST); + format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfdiv_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vdivD(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (DivVD src1 src2)); + ins_cost(VEC_COST); + format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfdiv_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector integer max/min + +instruct vmax(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && + n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); + match(Set dst (MaxV src1 src2)); + ins_cost(VEC_COST); + format %{ "vmax.vv $dst, $src1, $src2\t#@vmax" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli(t0, x0, sew); + __ vmax_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmin(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && + n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); + match(Set dst (MinV src1 src2)); + ins_cost(VEC_COST); + format %{ "vmin.vv $dst, $src1, $src2\t#@vmin" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli(t0, x0, sew); + __ vmin_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector float-point max/min + +instruct vmaxF(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MaxV src1 src2)); + effect(TEMP_DEF dst); + ins_cost(VEC_COST); + format %{ "vmaxF $dst, $src1, $src2\t#@vmaxF" %} + ins_encode %{ + __ minmax_FD_v(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), + false /* is_double */, false /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +instruct vmaxD(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MaxV src1 src2)); + effect(TEMP_DEF dst); + ins_cost(VEC_COST); + format %{ "vmaxD $dst, $src1, $src2\t#@vmaxD" %} + ins_encode %{ + __ minmax_FD_v(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), + true /* is_double */, false /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +instruct vminF(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MinV src1 src2)); + effect(TEMP_DEF dst); + ins_cost(VEC_COST); + format %{ "vminF $dst, $src1, $src2\t#@vminF" %} + ins_encode %{ + __ minmax_FD_v(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), + false /* is_double */, true /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +instruct vminD(vReg dst, vReg src1, vReg src2) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MinV src1 src2)); + effect(TEMP_DEF dst); + ins_cost(VEC_COST); + format %{ "vminD $dst, $src1, $src2\t#@vminD" %} + ins_encode %{ + __ minmax_FD_v(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), + true /* is_double */, true /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +// vector fmla + +// dst_src1 = dst_src1 + src2 * src3 +instruct vfmlaF(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3))); + ins_cost(VEC_COST); + format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vfmlaD(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3))); + ins_cost(VEC_COST); + format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector fmls + +// dst_src1 = dst_src1 + -src2 * src3 +// dst_src1 = dst_src1 + src2 * -src3 +instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3))); + match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3)))); + ins_cost(VEC_COST); + format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + -src2 * src3 +// dst_src1 = dst_src1 + src2 * -src3 +instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3))); + match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3)))); + ins_cost(VEC_COST); + format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector fnmla + +// dst_src1 = -dst_src1 + -src2 * src3 +// dst_src1 = -dst_src1 + src2 * -src3 +instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3))); + match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3)))); + ins_cost(VEC_COST); + format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -dst_src1 + -src2 * src3 +// dst_src1 = -dst_src1 + src2 * -src3 +instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3))); + match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3)))); + ins_cost(VEC_COST); + format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector fnmls + +// dst_src1 = -dst_src1 + src2 * src3 +instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3))); + ins_cost(VEC_COST); + format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = -dst_src1 + src2 * src3 +instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{ + predicate(UseFMA); + match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3))); + ins_cost(VEC_COST); + format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector mla + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaB(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (AddVB dst_src1 (MulVB src2 src3))); + ins_cost(VEC_COST); + format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaS(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (AddVS dst_src1 (MulVS src2 src3))); + ins_cost(VEC_COST); + format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaI(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (AddVI dst_src1 (MulVI src2 src3))); + ins_cost(VEC_COST); + format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 + src2 * src3 +instruct vmlaL(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (AddVL dst_src1 (MulVL src2 src3))); + ins_cost(VEC_COST); + format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmacc_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector mls + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsB(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (SubVB dst_src1 (MulVB src2 src3))); + ins_cost(VEC_COST); + format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsS(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (SubVS dst_src1 (MulVS src2 src3))); + ins_cost(VEC_COST); + format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsI(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (SubVI dst_src1 (MulVI src2 src3))); + ins_cost(VEC_COST); + format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// dst_src1 = dst_src1 - src2 * src3 +instruct vmlsL(vReg dst_src1, vReg src2, vReg src3) %{ + match(Set dst_src1 (SubVL dst_src1 (MulVL src2 src3))); + ins_cost(VEC_COST); + format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector mul + +instruct vmulB(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVB src1 src2)); + ins_cost(VEC_COST); + format %{ "vmul.vv $dst, $src1, $src2\t#@vmulB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmulS(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVS src1 src2)); + ins_cost(VEC_COST); + format %{ "vmul.vv $dst, $src1, $src2\t#@vmulS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmulI(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVI src1 src2)); + ins_cost(VEC_COST); + format %{ "vmul.vv $dst, $src1, $src2\t#@vmulI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmulL(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVL src1 src2)); + ins_cost(VEC_COST); + format %{ "vmul.vv $dst, $src1, $src2\t#@vmulL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmulF(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVF src1 src2)); + ins_cost(VEC_COST); + format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmulD(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (MulVD src1 src2)); + ins_cost(VEC_COST); + format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector fneg + +instruct vnegF(vReg dst, vReg src) %{ + match(Set dst (NegVF src)); + ins_cost(VEC_COST); + format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vnegD(vReg dst, vReg src) %{ + match(Set dst (NegVD src)); + ins_cost(VEC_COST); + format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// popcount vector + +instruct vpopcountI(iRegINoSp dst, vReg src) %{ + match(Set dst (PopCountVI src)); + format %{ "vpopc.m $dst, $src\t#@vpopcountI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vpopc_m(as_Register($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector add reduction + +instruct reduce_addB(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); + match(Set dst (AddReductionVI src1 src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vmv.s.x $tmp, $src1\t#@reduce_addB\n\t" + "vredsum.vs $tmp, $src2, $tmp\n\t" + "vmv.x.s $dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct reduce_addS(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (AddReductionVI src1 src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vmv.s.x $tmp, $src1\t#@reduce_addS\n\t" + "vredsum.vs $tmp, $src2, $tmp\n\t" + "vmv.x.s $dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (AddReductionVI src1 src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vmv.s.x $tmp, $src1\t#@reduce_addI\n\t" + "vredsum.vs $tmp, $src2, $tmp\n\t" + "vmv.x.s $dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct reduce_addL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); + match(Set dst (AddReductionVL src1 src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vmv.s.x $tmp, $src1\t#@reduce_addL\n\t" + "vredsum.vs $tmp, $src2, $tmp\n\t" + "vmv.x.s $dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct reduce_addF(fRegF src1_dst, vReg src2, vReg tmp) %{ + match(Set src1_dst (AddReductionVF src1_dst src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addF\n\t" + "vfredosum.vs $tmp, $src2, $tmp\n\t" + "vfmv.f.s $src1_dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); + __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct reduce_addD(fRegD src1_dst, vReg src2, vReg tmp) %{ + match(Set src1_dst (AddReductionVD src1_dst src2)); + effect(TEMP tmp); + ins_cost(VEC_COST); + format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addD\n\t" + "vfredosum.vs $tmp, $src2, $tmp\n\t" + "vfmv.f.s $src1_dst, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); + __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), + as_VectorRegister($tmp$$reg)); + __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector integer max reduction +instruct vreduce_maxB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_maxB $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + Label Ldone; + __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_maxS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_maxS $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + Label Ldone; + __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_maxI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_maxI $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_maxL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_maxL $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector integer min reduction +instruct vreduce_minB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_minB $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + Label Ldone; + __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_minS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_minS $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + Label Ldone; + __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); + __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); + __ bind(Ldone); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_minI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_minI $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_minL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP tmp); + format %{ "vreduce_minL $dst, $src1, $src2, $tmp" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); + __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); + __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector float max reduction + +instruct vreduce_maxF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); + format %{ "reduce_maxF $dst, $src1, $src2, $tmp1, $tmp2" %} + ins_encode %{ + __ reduce_minmax_FD_v($dst$$FloatRegister, + $src1$$FloatRegister, as_VectorRegister($src2$$reg), + as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), + false /* is_double */, false /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_maxD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MaxReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); + format %{ "reduce_maxD $dst, $src1, $src2, $tmp1, $tmp2" %} + ins_encode %{ + __ reduce_minmax_FD_v($dst$$FloatRegister, + $src1$$FloatRegister, as_VectorRegister($src2$$reg), + as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), + true /* is_double */, false /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +// vector float min reduction + +instruct vreduce_minF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); + format %{ "reduce_minF $dst, $src1, $src2, $tmp1, $tmp2" %} + ins_encode %{ + __ reduce_minmax_FD_v($dst$$FloatRegister, + $src1$$FloatRegister, as_VectorRegister($src2$$reg), + as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), + false /* is_double */, true /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +instruct vreduce_minD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MinReductionV src1 src2)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); + format %{ "reduce_minD $dst, $src1, $src2, $tmp1, $tmp2" %} + ins_encode %{ + __ reduce_minmax_FD_v($dst$$FloatRegister, + $src1$$FloatRegister, as_VectorRegister($src2$$reg), + as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), + true /* is_double */, true /* is_min */); + %} + ins_pipe(pipe_slow); +%} + +// vector Math.rint, floor, ceil + +instruct vroundD(vReg dst, vReg src, immI rmode) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "vroundD $dst, $src, $rmode" %} + ins_encode %{ + switch ($rmode$$constant) { + case RoundDoubleModeNode::rmode_rint: + __ csrwi(CSR_FRM, C2_MacroAssembler::rne); + __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_floor: + __ csrwi(CSR_FRM, C2_MacroAssembler::rdn); + __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_ceil: + __ csrwi(CSR_FRM, C2_MacroAssembler::rup); + __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + break; + default: + ShouldNotReachHere(); + break; + } + %} + ins_pipe(pipe_slow); +%} + +// vector replicate + +instruct replicateB(vReg dst, iRegIorL2I src) %{ + match(Set dst (ReplicateB src)); + ins_cost(VEC_COST); + format %{ "vmv.v.x $dst, $src\t#@replicateB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateS(vReg dst, iRegIorL2I src) %{ + match(Set dst (ReplicateS src)); + ins_cost(VEC_COST); + format %{ "vmv.v.x $dst, $src\t#@replicateS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateI(vReg dst, iRegIorL2I src) %{ + match(Set dst (ReplicateI src)); + ins_cost(VEC_COST); + format %{ "vmv.v.x $dst, $src\t#@replicateI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateL(vReg dst, iRegL src) %{ + match(Set dst (ReplicateL src)); + ins_cost(VEC_COST); + format %{ "vmv.v.x $dst, $src\t#@replicateL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateB_imm5(vReg dst, immI5 con) %{ + match(Set dst (ReplicateB con)); + ins_cost(VEC_COST); + format %{ "vmv.v.i $dst, $con\t#@replicateB_imm5" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateS_imm5(vReg dst, immI5 con) %{ + match(Set dst (ReplicateS con)); + ins_cost(VEC_COST); + format %{ "vmv.v.i $dst, $con\t#@replicateS_imm5" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateI_imm5(vReg dst, immI5 con) %{ + match(Set dst (ReplicateI con)); + ins_cost(VEC_COST); + format %{ "vmv.v.i $dst, $con\t#@replicateI_imm5" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateL_imm5(vReg dst, immL5 con) %{ + match(Set dst (ReplicateL con)); + ins_cost(VEC_COST); + format %{ "vmv.v.i $dst, $con\t#@replicateL_imm5" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateF(vReg dst, fRegF src) %{ + match(Set dst (ReplicateF src)); + ins_cost(VEC_COST); + format %{ "vfmv.v.f $dst, $src\t#@replicateF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); + %} + ins_pipe(pipe_slow); +%} + +instruct replicateD(vReg dst, fRegD src) %{ + match(Set dst (ReplicateD src)); + ins_cost(VEC_COST); + format %{ "vfmv.v.f $dst, $src\t#@replicateD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); + %} + ins_pipe(pipe_slow); +%} + +// vector shift + +instruct vasrB(vReg dst, vReg src, vReg shift) %{ + match(Set dst (RShiftVB src shift)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift 7\t#@vasrB\n\t" + "vsra.vi $dst, $src, 7, Assembler::v0_t\n\t" + "vmnot.m v0, v0\n\t" + "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + // if shift > BitsPerByte - 1, clear the low BitsPerByte - 1 bits + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + BitsPerByte - 1, Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrS(vReg dst, vReg src, vReg shift) %{ + match(Set dst (RShiftVS src shift)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift, 15\t#@vasrS\n\t" + "vsra.vi $dst, $src, 15, Assembler::v0_t\n\t" + "vmnot.m v0, v0\n\t" + "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + // if shift > BitsPerShort - 1, clear the low BitsPerShort - 1 bits + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + BitsPerShort - 1, Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrI(vReg dst, vReg src, vReg shift) %{ + match(Set dst (RShiftVI src shift)); + ins_cost(VEC_COST); + format %{ "vsra.vv $dst, $src, $shift\t#@vasrI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrL(vReg dst, vReg src, vReg shift) %{ + match(Set dst (RShiftVL src shift)); + ins_cost(VEC_COST); + format %{ "vsra.vv $dst, $src, $shift\t#@vasrL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslB(vReg dst, vReg src, vReg shift) %{ + match(Set dst (LShiftVB src shift)); + ins_cost(VEC_COST); + effect( TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift, 7\t#@vlslB\n\t" + "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" + "vmnot.m v0, v0\n\t" + "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + // if shift > BitsPerByte - 1, clear the element + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg), Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslS(vReg dst, vReg src, vReg shift) %{ + match(Set dst (LShiftVS src shift)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift, 15\t#@vlslS\n\t" + "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" + "vmnot.m v0, v0\n\t" + "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + // if shift > BitsPerShort - 1, clear the element + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg), Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslI(vReg dst, vReg src, vReg shift) %{ + match(Set dst (LShiftVI src shift)); + ins_cost(VEC_COST); + format %{ "vsll.vv $dst, $src, $shift\t#@vlslI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslL(vReg dst, vReg src, vReg shift) %{ + match(Set dst (LShiftVL src shift)); + ins_cost(VEC_COST); + format %{ "vsll.vv $dst, $src, $shift\t# vector (D)" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrB(vReg dst, vReg src, vReg shift) %{ + match(Set dst (URShiftVB src shift)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift, 7\t#@vlsrB\n\t" + "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" + "vmnot.m v0, v0, v0\n\t" + "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + // if shift > BitsPerByte - 1, clear the element + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg), Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrS(vReg dst, vReg src, vReg shift) %{ + match(Set dst (URShiftVS src shift)); + ins_cost(VEC_COST); + effect(TEMP_DEF dst); + format %{ "vmsgtu.vi v0, $shift, 15\t#@vlsrS\n\t" + "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" + "vmnot.m v0, v0\n\t" + "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + // if shift > BitsPerShort - 1, clear the element + __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg), Assembler::v0_t); + // otherwise, shift + __ vmnot_m(v0, v0); + __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + + +instruct vlsrI(vReg dst, vReg src, vReg shift) %{ + match(Set dst (URShiftVI src shift)); + ins_cost(VEC_COST); + format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + + +instruct vlsrL(vReg dst, vReg src, vReg shift) %{ + match(Set dst (URShiftVL src shift)); + ins_cost(VEC_COST); + format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($shift$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrB_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (RShiftVB src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsra.vi $dst, $src, $shift\t#@vasrB_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e8); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + if (con >= BitsPerByte) con = BitsPerByte - 1; + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrS_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (RShiftVS src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsra.vi $dst, $src, $shift\t#@vasrS_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e16); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + if (con >= BitsPerShort) con = BitsPerShort - 1; + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrI_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (RShiftVI src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vasrI_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e32); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vasrL_imm(vReg dst, vReg src, immI shift) %{ + predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); + match(Set dst (RShiftVL src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vasrL_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e64); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (URShiftVB src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrB_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e8); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + if (con >= BitsPerByte) { + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (URShiftVS src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrS_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e16); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + if (con >= BitsPerShort) { + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (URShiftVI src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrI_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e32); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{ + predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); + match(Set dst (URShiftVL src (RShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrL_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e64); + if (con == 0) { + __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslB_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (LShiftVB src (LShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsll.vi $dst, $src, $shift\t#@vlslB_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e8); + if (con >= BitsPerByte) { + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslS_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (LShiftVS src (LShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsll.vi $dst, $src, $shift\t#@vlslS_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e16); + if (con >= BitsPerShort) { + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), + as_VectorRegister($src$$reg)); + return; + } + __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslI_imm(vReg dst, vReg src, immI shift) %{ + match(Set dst (LShiftVI src (LShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsll.vi $dst, $src, $shift\t#@vlslI_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e32); + __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vlslL_imm(vReg dst, vReg src, immI shift) %{ + predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); + match(Set dst (LShiftVL src (LShiftCntV shift))); + ins_cost(VEC_COST); + format %{ "vsll.vi $dst, $src, $shift\t#@vlslL_imm" %} + ins_encode %{ + uint32_t con = (unsigned)$shift$$constant & 0x1f; + __ vsetvli(t0, x0, Assembler::e64); + __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); + %} + ins_pipe(pipe_slow); +%} + +instruct vshiftcntB(vReg dst, iRegIorL2I cnt) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_BYTE); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vshiftcntS(vReg dst, iRegIorL2I cnt) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_SHORT || + n->bottom_type()->is_vect()->element_basic_type() == T_CHAR); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vshiftcntI(vReg dst, iRegIorL2I cnt) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vshiftcntL(vReg dst, iRegIorL2I cnt) %{ + predicate(n->bottom_type()->is_vect()->element_basic_type() == T_LONG); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector sqrt + +instruct vsqrtF(vReg dst, vReg src) %{ + match(Set dst (SqrtVF src)); + ins_cost(VEC_COST); + format %{ "vfsqrt.v $dst, $src\t#@vsqrtF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsqrtD(vReg dst, vReg src) %{ + match(Set dst (SqrtVD src)); + ins_cost(VEC_COST); + format %{ "vfsqrt.v $dst, $src\t#@vsqrtD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector sub + +instruct vsubB(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVB src1 src2)); + ins_cost(VEC_COST); + format %{ "vsub.vv $dst, $src1, $src2\t#@vsubB" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e8); + __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsubS(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVS src1 src2)); + ins_cost(VEC_COST); + format %{ "vsub.vv $dst, $src1, $src2\t#@vsubS" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e16); + __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsubI(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVI src1 src2)); + ins_cost(VEC_COST); + format %{ "vsub.vv $dst, $src1, $src2\t#@vsubI" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsubL(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVL src1 src2)); + ins_cost(VEC_COST); + format %{ "vsub.vv $dst, $src1, $src2\t#@vsubL" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsubF(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVF src1 src2)); + ins_cost(VEC_COST); + format %{ "vfsub.vv $dst, $src1, $src2\t@vsubF" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e32); + __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vsubD(vReg dst, vReg src1, vReg src2) %{ + match(Set dst (SubVD src1 src2)); + ins_cost(VEC_COST); + format %{ "vfsub.vv $dst, $src1, $src2\t#@vsubD" %} + ins_encode %{ + __ vsetvli(t0, x0, Assembler::e64); + __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vstring_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, vReg_V1 v1, + vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) +%{ + predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); + + format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsL" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_equals_v($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, 1); + %} + ins_pipe(pipe_class_memory); +%} + +instruct vstring_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, vReg_V1 v1, + vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) +%{ + predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); + + format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_equals_v($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, 2); + %} + ins_pipe(pipe_class_memory); +%} + +instruct varray_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) +%{ + predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (AryEq ary1 ary2)); + effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); + + format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsB // KILL $tmp" %} + ins_encode %{ + __ arrays_equals_v($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, 1); + %} + ins_pipe(pipe_class_memory); +%} + +instruct varray_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) +%{ + predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); + + format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsC // KILL $tmp" %} + ins_encode %{ + __ arrays_equals_v($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, 2); + %} + ins_pipe(pipe_class_memory); +%} + +instruct vstring_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, + iRegP_R28 tmp1, iRegL_R29 tmp2) +%{ + predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); + match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, + TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareU" %} + ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ string_compare_v($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, + StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_memory); +%} +instruct vstring_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, + iRegP_R28 tmp1, iRegL_R29 tmp2) +%{ + predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); + match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, + TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareL" %} + ins_encode %{ + __ string_compare_v($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, + StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_memory); +%} + +instruct vstring_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, + iRegP_R28 tmp1, iRegL_R29 tmp2) +%{ + predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); + match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, + TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); + + format %{"String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareUL" %} + ins_encode %{ + __ string_compare_v($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, + StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_memory); +%} +instruct vstring_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, + iRegP_R28 tmp1, iRegL_R29 tmp2) +%{ + predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); + match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, + TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); + + format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareLU" %} + ins_encode %{ + __ string_compare_v($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, + StrIntrinsicNode::LU); + %} + ins_pipe(pipe_class_memory); +%} + +// fast byte[] to char[] inflation +instruct vstring_inflate(Universe dummy, iRegP_R10 src, iRegP_R11 dst, iRegI_R12 len, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) +%{ + predicate(UseRVV); + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP v1, TEMP v2, TEMP v3, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len); + + format %{ "String Inflate $src,$dst" %} + ins_encode %{ + __ byte_array_inflate_v($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// encode char[] to byte[] in ISO_8859_1 +instruct vencode_iso_array(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) +%{ + predicate(UseRVV); + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, + TEMP v1, TEMP v2, TEMP v3, TEMP tmp); + + format %{ "Encode array $src,$dst,$len -> $result" %} + ins_encode %{ + __ encode_iso_array_v($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp$$Register); + %} + ins_pipe( pipe_class_memory ); +%} + +// fast char[] to byte[] compression +instruct vstring_compress(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) +%{ + predicate(UseRVV); + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, + TEMP v1, TEMP v2, TEMP v3, TEMP tmp); + + format %{ "String Compress $src,$dst -> $result // KILL R11, R12, R13" %} + ins_encode %{ + __ char_array_compress_v($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vcount_positives(iRegP_R11 ary, iRegI_R12 len, iRegI_R10 result, iRegL tmp) +%{ + predicate(UseRVV); + match(Set result (CountPositives ary len)); + effect(USE_KILL ary, USE_KILL len, TEMP tmp); + + format %{ "count positives byte[] $ary, $len -> $result" %} + ins_encode %{ + __ count_positives_v($ary$$Register, $len$$Register, $result$$Register, $tmp$$Register); + %} + + ins_pipe(pipe_slow); +%} + +instruct vstringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) +%{ + predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, + TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); + + format %{ "StringUTF16 IndexOf char[] $str1, $cnt1, $ch -> $result" %} + + ins_encode %{ + __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, + $result$$Register, $tmp1$$Register, $tmp2$$Register, + false /* isL */); + %} + + ins_pipe(pipe_class_memory); +%} + +instruct vstringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, + iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, + vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) +%{ + predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, + TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); + + format %{ "StringLatin1 IndexOf char[] $str1, $cnt1, $ch -> $result" %} + + ins_encode %{ + __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, + $result$$Register, $tmp1$$Register, $tmp2$$Register, + true /* isL */); + %} + + ins_pipe(pipe_class_memory); +%} + +// clearing of an array +instruct vclearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy, + vReg_V1 vReg1, vReg_V2 vReg2, vReg_V3 vReg3) +%{ + predicate(UseRVV); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL cnt, USE_KILL base, TEMP vReg1, TEMP vReg2, TEMP vReg3); + + format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %} + + ins_encode %{ + __ clear_array_v($base$$Register, $cnt$$Register); + %} + + ins_pipe(pipe_class_memory); +%} diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f85d4b25a7669e4975905634ecba9dc620fb0df9 --- /dev/null +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -0,0 +1,2761 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/debugInfoRec.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "compiler/oopMap.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/compiledICHolder.hpp" +#include "oops/klass.inline.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/signature.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" +#include "utilities/formatBuffer.hpp" +#include "vmreg_riscv.inline.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "adfiles/ad_riscv.hpp" +#include "opto/runtime.hpp" +#endif + +#define __ masm-> + +const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; + +class SimpleRuntimeFrame { +public: + + // Most of the runtime stubs have this simple frame layout. + // This class exists to make the layout shared in one place. + // Offsets are for compiler stack slots, which are jints. + enum layout { + // The frame sender code expects that fp will be in the "natural" place and + // will override any oopMap setting for it. We must therefore force the layout + // so that it agrees with the frame sender code. + // we don't expect any arg reg save area so riscv asserts that + // frame::arg_reg_save_area_bytes == 0 + fp_off = 0, fp_off2, + return_off, return_off2, + framesize + }; +}; + +class RegisterSaver { + const bool _save_vectors; + public: + RegisterSaver(bool save_vectors) : _save_vectors(UseRVV && save_vectors) {} + ~RegisterSaver() {} + OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); + void restore_live_registers(MacroAssembler* masm); + + // Offsets into the register save area + // Used by deoptimization when it is managing result register + // values on its own + // gregs:28, float_register:32; except: x1(ra) & x2(sp) & gp(x3) & tp(x4) + // |---v0---|<---SP + // |---v1---|save vectors only in generate_handler_blob + // |-- .. --| + // |---v31--|----- + // |---f0---| + // |---f1---| + // | .. | + // |---f31--| + // |---reserved slot for stack alignment---| + // |---x5---| + // | x6 | + // |---.. --| + // |---x31--| + // |---fp---| + // |---ra---| + int v0_offset_in_bytes(void) { return 0; } + int f0_offset_in_bytes(void) { + int f0_offset = 0; +#ifdef COMPILER2 + if (_save_vectors) { + f0_offset += Matcher::scalable_vector_reg_size(T_INT) * VectorRegisterImpl::number_of_registers * + BytesPerInt; + } +#endif + return f0_offset; + } + int reserved_slot_offset_in_bytes(void) { + return f0_offset_in_bytes() + + FloatRegisterImpl::max_slots_per_register * + FloatRegisterImpl::number_of_registers * + BytesPerInt; + } + + int reg_offset_in_bytes(Register r) { + assert (r->encoding() > 4, "ra, sp, gp and tp not saved"); + return reserved_slot_offset_in_bytes() + (r->encoding() - 4 /* x1, x2, x3, x4 */) * wordSize; + } + + int freg_offset_in_bytes(FloatRegister f) { + return f0_offset_in_bytes() + f->encoding() * wordSize; + } + + int ra_offset_in_bytes(void) { + return reserved_slot_offset_in_bytes() + + (RegisterImpl::number_of_registers - 3) * + RegisterImpl::max_slots_per_register * + BytesPerInt; + } +}; + +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { + int vector_size_in_bytes = 0; + int vector_size_in_slots = 0; +#ifdef COMPILER2 + if (_save_vectors) { + vector_size_in_bytes += Matcher::scalable_vector_reg_size(T_BYTE); + vector_size_in_slots += Matcher::scalable_vector_reg_size(T_INT); + } +#endif + + assert_cond(masm != NULL && total_frame_words != NULL); + int frame_size_in_bytes = align_up(additional_frame_words * wordSize + ra_offset_in_bytes() + wordSize, 16); + // OopMap frame size is in compiler stack slots (jint's) not bytes or words + int frame_size_in_slots = frame_size_in_bytes / BytesPerInt; + // The caller will allocate additional_frame_words + int additional_frame_slots = additional_frame_words * wordSize / BytesPerInt; + // CodeBlob frame size is in words. + int frame_size_in_words = frame_size_in_bytes / wordSize; + *total_frame_words = frame_size_in_words; + + // Save Integer, Float and Vector registers. + __ enter(); + __ push_CPU_state(_save_vectors, vector_size_in_bytes); + + // Set an oopmap for the call site. This oopmap will map all + // oop-registers and debug-info registers as callee-saved. This + // will allow deoptimization at this safepoint to find all possible + // debug-info recordings, as well as let GC find all oops. + + OopMapSet *oop_maps = new OopMapSet(); + OopMap* oop_map = new OopMap(frame_size_in_slots, 0); + assert_cond(oop_maps != NULL && oop_map != NULL); + + int sp_offset_in_slots = 0; + int step_in_slots = 0; + if (_save_vectors) { + step_in_slots = vector_size_in_slots; + for (int i = 0; i < VectorRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { + VectorRegister r = as_VectorRegister(i); + oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset_in_slots), r->as_VMReg()); + } + } + + step_in_slots = FloatRegisterImpl::max_slots_per_register; + for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { + FloatRegister r = as_FloatRegister(i); + oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset_in_slots), r->as_VMReg()); + } + + step_in_slots = RegisterImpl::max_slots_per_register; + // skip the slot reserved for alignment, see MacroAssembler::push_reg; + // also skip x5 ~ x6 on the stack because they are caller-saved registers. + sp_offset_in_slots += RegisterImpl::max_slots_per_register * 3; + // besides, we ignore x0 ~ x4 because push_CPU_state won't push them on the stack. + for (int i = 7; i < RegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { + Register r = as_Register(i); + if (r != xthread) { + oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset_in_slots + additional_frame_slots), r->as_VMReg()); + } + } + + return oop_map; +} + +void RegisterSaver::restore_live_registers(MacroAssembler* masm) { + assert_cond(masm != NULL); +#ifdef COMPILER2 + __ pop_CPU_state(_save_vectors, Matcher::scalable_vector_reg_size(T_BYTE)); +#else + __ pop_CPU_state(_save_vectors); +#endif + __ leave(); +} + +// Is vector's size (in bytes) bigger than a size saved by default? +// riscv does not ovlerlay the floating-point registers on vector registers like aarch64. +bool SharedRuntime::is_wide_vector(int size) { + return UseRVV; +} + +// The java_calling_convention describes stack locations as ideal slots on +// a frame with no abi restrictions. Since we must observe abi restrictions +// (like the placement of the register window) the slots must be biased by +// the following value. +static int reg2offset_in(VMReg r) { + // Account for saved fp and ra + // This should really be in_preserve_stack_slots + return r->reg2stack() * VMRegImpl::stack_slot_size; +} + +static int reg2offset_out(VMReg r) { + return (r->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; +} + +// --------------------------------------------------------------------------- +// Read the array of BasicTypes from a signature, and compute where the +// arguments should go. Values in the VMRegPair regs array refer to 4-byte +// quantities. Values less than VMRegImpl::stack0 are registers, those above +// refer to 4-byte stack slots. All stack slots are based off of the stack pointer +// as framesizes are fixed. +// VMRegImpl::stack0 refers to the first slot 0(sp). +// and VMRegImpl::stack0+1 refers to the memory word 4-byes higher. Register +// up to RegisterImpl::number_of_registers) are the 64-bit +// integer registers. + +// Note: the INPUTS in sig_bt are in units of Java argument words, +// which are 64-bit. The OUTPUTS are in 32-bit units. + +// The Java calling convention is a "shifted" version of the C ABI. +// By skipping the first C ABI register we can call non-static jni +// methods with small numbers of arguments without having to shuffle +// the arguments at all. Since we control the java ABI we ought to at +// least get some advantage out of it. + +int SharedRuntime::java_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, + int total_args_passed) { + // Create the mapping between argument positions and + // registers. + static const Register INT_ArgReg[Argument::n_int_register_parameters_j] = { + j_rarg0, j_rarg1, j_rarg2, j_rarg3, + j_rarg4, j_rarg5, j_rarg6, j_rarg7 + }; + static const FloatRegister FP_ArgReg[Argument::n_float_register_parameters_j] = { + j_farg0, j_farg1, j_farg2, j_farg3, + j_farg4, j_farg5, j_farg6, j_farg7 + }; + + uint int_args = 0; + uint fp_args = 0; + uint stk_args = 0; // inc by 2 each time + + for (int i = 0; i < total_args_passed; i++) { + switch (sig_bt[i]) { + case T_BOOLEAN: // fall through + case T_CHAR: // fall through + case T_BYTE: // fall through + case T_SHORT: // fall through + case T_INT: + if (int_args < Argument::n_int_register_parameters_j) { + regs[i].set1(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set1(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_VOID: + // halves of T_LONG or T_DOUBLE + assert(i != 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "expecting half"); + regs[i].set_bad(); + break; + case T_LONG: // fall through + assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); + case T_OBJECT: // fall through + case T_ARRAY: // fall through + case T_ADDRESS: + if (int_args < Argument::n_int_register_parameters_j) { + regs[i].set2(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_FLOAT: + if (fp_args < Argument::n_float_register_parameters_j) { + regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg()); + } else { + regs[i].set1(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_DOUBLE: + assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); + if (fp_args < Argument::n_float_register_parameters_j) { + regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg()); + } else { + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + default: + ShouldNotReachHere(); + } + } + + return align_up(stk_args, 2); +} + +// Patch the callers callsite with entry to compiled code if it exists. +static void patch_callers_callsite(MacroAssembler *masm) { + assert_cond(masm != NULL); + Label L; + __ ld(t0, Address(xmethod, in_bytes(Method::code_offset()))); + __ beqz(t0, L); + + __ enter(); + __ push_CPU_state(); + + // VM needs caller's callsite + // VM needs target method + // This needs to be a long call since we will relocate this adapter to + // the codeBuffer and it may not reach + +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + + __ mv(c_rarg0, xmethod); + __ mv(c_rarg1, ra); + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite)), offset); + __ jalr(x1, t0, offset); + + // Explicit fence.i required because fixup_callers_callsite may change the code + // stream. + __ safepoint_ifence(); + + __ pop_CPU_state(); + // restore sp + __ leave(); + __ bind(L); +} + +static void gen_c2i_adapter(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs, + Label& skip_fixup) { + // Before we get into the guts of the C2I adapter, see if we should be here + // at all. We've come from compiled code and are attempting to jump to the + // interpreter, which means the caller made a static call to get here + // (vcalls always get a compiled target if there is one). Check for a + // compiled target. If there is one, we need to patch the caller's call. + patch_callers_callsite(masm); + + __ bind(skip_fixup); + + int words_pushed = 0; + + // Since all args are passed on the stack, total_args_passed * + // Interpreter::stackElementSize is the space we need. + + int extraspace = total_args_passed * Interpreter::stackElementSize; + + __ mv(x30, sp); + + // stack is aligned, keep it that way + extraspace = align_up(extraspace, 2 * wordSize); + + if (extraspace) { + __ sub(sp, sp, extraspace); + } + + // Now write the args into the outgoing interpreter space + for (int i = 0; i < total_args_passed; i++) { + if (sig_bt[i] == T_VOID) { + assert(i > 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "missing half"); + continue; + } + + // offset to start parameters + int st_off = (total_args_passed - i - 1) * Interpreter::stackElementSize; + int next_off = st_off - Interpreter::stackElementSize; + + // Say 4 args: + // i st_off + // 0 32 T_LONG + // 1 24 T_VOID + // 2 16 T_OBJECT + // 3 8 T_BOOL + // - 0 return address + // + // However to make thing extra confusing. Because we can fit a Java long/double in + // a single slot on a 64 bt vm and it would be silly to break them up, the interpreter + // leaves one slot empty and only stores to a single slot. In this case the + // slot that is occupied is the T_VOID slot. See I said it was confusing. + + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_stack()) { + // memory to memory use t0 + int ld_off = (r_1->reg2stack() * VMRegImpl::stack_slot_size + + extraspace + + words_pushed * wordSize); + if (!r_2->is_valid()) { + __ lwu(t0, Address(sp, ld_off)); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); + } else { + __ ld(t0, Address(sp, ld_off), /*temp register*/esp); + + // Two VMREgs|OptoRegs can be T_OBJECT, T_ADDRESS, T_DOUBLE, T_LONG + // T_DOUBLE and T_LONG use two slots in the interpreter + if ( sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { + // ld_off == LSW, ld_off+wordSize == MSW + // st_off == MSW, next_off == LSW + __ sd(t0, Address(sp, next_off), /*temp register*/esp); +#ifdef ASSERT + // Overwrite the unused slot with known junk + __ li(t0, 0xdeadffffdeadaaaaul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + } else { + __ sd(t0, Address(sp, st_off), /*temp register*/esp); + } + } + } else if (r_1->is_Register()) { + Register r = r_1->as_Register(); + if (!r_2->is_valid()) { + // must be only an int (or less ) so move only 32bits to slot + __ sd(r, Address(sp, st_off)); + } else { + // Two VMREgs|OptoRegs can be T_OBJECT, T_ADDRESS, T_DOUBLE, T_LONG + // T_DOUBLE and T_LONG use two slots in the interpreter + if ( sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { + // long/double in gpr +#ifdef ASSERT + // Overwrite the unused slot with known junk + __ li(t0, 0xdeadffffdeadaaabul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + __ sd(r, Address(sp, next_off)); + } else { + __ sd(r, Address(sp, st_off)); + } + } + } else { + assert(r_1->is_FloatRegister(), ""); + if (!r_2->is_valid()) { + // only a float use just part of the slot + __ fsw(r_1->as_FloatRegister(), Address(sp, st_off)); + } else { +#ifdef ASSERT + // Overwrite the unused slot with known junk + __ li(t0, 0xdeadffffdeadaaacul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + __ fsd(r_1->as_FloatRegister(), Address(sp, next_off)); + } + } + } + + __ mv(esp, sp); // Interp expects args on caller's expression stack + + __ ld(t0, Address(xmethod, in_bytes(Method::interpreter_entry_offset()))); + __ jr(t0); +} + +void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs) { + // Cut-out for having no stack args. + int comp_words_on_stack = align_up(comp_args_on_stack * VMRegImpl::stack_slot_size, wordSize) >> LogBytesPerWord; + if (comp_args_on_stack != 0) { + __ sub(t0, sp, comp_words_on_stack * wordSize); + __ andi(sp, t0, -16); + } + + // Will jump to the compiled code just as if compiled code was doing it. + // Pre-load the register-jump target early, to schedule it better. + __ ld(t1, Address(xmethod, in_bytes(Method::from_compiled_offset()))); + + // Now generate the shuffle code. + for (int i = 0; i < total_args_passed; i++) { + if (sig_bt[i] == T_VOID) { + assert(i > 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "missing half"); + continue; + } + + // Pick up 0, 1 or 2 words from SP+offset. + + assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), + "scrambled load targets?"); + // Load in argument order going down. + int ld_off = (total_args_passed - i - 1) * Interpreter::stackElementSize; + // Point to interpreter value (vs. tag) + int next_off = ld_off - Interpreter::stackElementSize; + + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_stack()) { + // Convert stack slot to an SP offset (+ wordSize to account for return address ) + int st_off = regs[i].first()->reg2stack() * VMRegImpl::stack_slot_size; + if (!r_2->is_valid()) { + __ lw(t0, Address(esp, ld_off)); + __ sd(t0, Address(sp, st_off), /*temp register*/t2); + } else { + // + // We are using two optoregs. This can be either T_OBJECT, + // T_ADDRESS, T_LONG, or T_DOUBLE the interpreter allocates + // two slots but only uses one for thr T_LONG or T_DOUBLE case + // So we must adjust where to pick up the data to match the + // interpreter. + // + // Interpreter local[n] == MSW, local[n+1] == LSW however locals + // are accessed as negative so LSW is at LOW address + + // ld_off is MSW so get LSW + const int offset = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? + next_off : ld_off; + __ ld(t0, Address(esp, offset)); + // st_off is LSW (i.e. reg.first()) + __ sd(t0, Address(sp, st_off), /*temp register*/t2); + } + } else if (r_1->is_Register()) { // Register argument + Register r = r_1->as_Register(); + if (r_2->is_valid()) { + // + // We are using two VMRegs. This can be either T_OBJECT, + // T_ADDRESS, T_LONG, or T_DOUBLE the interpreter allocates + // two slots but only uses one for thr T_LONG or T_DOUBLE case + // So we must adjust where to pick up the data to match the + // interpreter. + + const int offset = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? + next_off : ld_off; + + // this can be a misaligned move + __ ld(r, Address(esp, offset)); + } else { + // sign extend and use a full word? + __ lw(r, Address(esp, ld_off)); + } + } else { + if (!r_2->is_valid()) { + __ flw(r_1->as_FloatRegister(), Address(esp, ld_off)); + } else { + __ fld(r_1->as_FloatRegister(), Address(esp, next_off)); + } + } + } + + // 6243940 We might end up in handle_wrong_method if + // the callee is deoptimized as we race thru here. If that + // happens we don't want to take a safepoint because the + // caller frame will look interpreted and arguments are now + // "compiled" so it is much better to make this transition + // invisible to the stack walking code. Unfortunately if + // we try and find the callee by normal means a safepoint + // is possible. So we stash the desired callee in the thread + // and the vm will find there should this case occur. + + __ sd(xmethod, Address(xthread, JavaThread::callee_target_offset())); + + __ jr(t1); +} + +// --------------------------------------------------------------- +AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs, + AdapterFingerPrint* fingerprint) { + address i2c_entry = __ pc(); + gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); + + address c2i_unverified_entry = __ pc(); + Label skip_fixup; + + Label ok; + + const Register holder = t1; + const Register receiver = j_rarg0; + const Register tmp = t2; // A call-clobbered register not used for arg passing + + // ------------------------------------------------------------------------- + // Generate a C2I adapter. On entry we know xmethod holds the Method* during calls + // to the interpreter. The args start out packed in the compiled layout. They + // need to be unpacked into the interpreter layout. This will almost always + // require some stack space. We grow the current (compiled) stack, then repack + // the args. We finally end in a jump to the generic interpreter entry point. + // On exit from the interpreter, the interpreter will restore our SP (lest the + // compiled code, which relys solely on SP and not FP, get sick). + + { + __ block_comment("c2i_unverified_entry {"); + __ load_klass(t0, receiver); + __ ld(tmp, Address(holder, CompiledICHolder::holder_klass_offset())); + __ ld(xmethod, Address(holder, CompiledICHolder::holder_metadata_offset())); + __ beq(t0, tmp, ok); + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + + __ bind(ok); + // Method might have been compiled since the call site was patched to + // interpreted; if that is the case treat it as a miss so we can get + // the call site corrected. + __ ld(t0, Address(xmethod, in_bytes(Method::code_offset()))); + __ beqz(t0, skip_fixup); + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + __ block_comment("} c2i_unverified_entry"); + } + + address c2i_entry = __ pc(); + + // Class initialization barrier for static methods + address c2i_no_clinit_check_entry = NULL; + if (VM_Version::supports_fast_class_init_checks()) { + Label L_skip_barrier; + + { // Bypass the barrier for non-static methods + __ lwu(t0, Address(xmethod, Method::access_flags_offset())); + __ andi(t1, t0, JVM_ACC_STATIC); + __ beqz(t1, L_skip_barrier); // non-static + } + + __ load_method_holder(t1, xmethod); + __ clinit_barrier(t1, t0, &L_skip_barrier); + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + + __ bind(L_skip_barrier); + c2i_no_clinit_check_entry = __ pc(); + } + + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->c2i_entry_barrier(masm); + + gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); + + __ flush(); + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); +} + +int SharedRuntime::vector_calling_convention(VMRegPair *regs, + uint num_bits, + uint total_args_passed) { + Unimplemented(); + return 0; +} + +int SharedRuntime::c_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, + VMRegPair *regs2, + int total_args_passed) { + assert(regs2 == NULL, "not needed on riscv"); + + // We return the amount of VMRegImpl stack slots we need to reserve for all + // the arguments NOT counting out_preserve_stack_slots. + + static const Register INT_ArgReg[Argument::n_int_register_parameters_c] = { + c_rarg0, c_rarg1, c_rarg2, c_rarg3, + c_rarg4, c_rarg5, c_rarg6, c_rarg7 + }; + static const FloatRegister FP_ArgReg[Argument::n_float_register_parameters_c] = { + c_farg0, c_farg1, c_farg2, c_farg3, + c_farg4, c_farg5, c_farg6, c_farg7 + }; + + uint int_args = 0; + uint fp_args = 0; + uint stk_args = 0; // inc by 2 each time + + for (int i = 0; i < total_args_passed; i++) { + switch (sig_bt[i]) { + case T_BOOLEAN: // fall through + case T_CHAR: // fall through + case T_BYTE: // fall through + case T_SHORT: // fall through + case T_INT: + if (int_args < Argument::n_int_register_parameters_c) { + regs[i].set1(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set1(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_LONG: // fall through + assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); + case T_OBJECT: // fall through + case T_ARRAY: // fall through + case T_ADDRESS: // fall through + case T_METADATA: + if (int_args < Argument::n_int_register_parameters_c) { + regs[i].set2(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_FLOAT: + if (fp_args < Argument::n_float_register_parameters_c) { + regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg()); + } else if (int_args < Argument::n_int_register_parameters_c) { + regs[i].set1(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set1(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_DOUBLE: + assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); + if (fp_args < Argument::n_float_register_parameters_c) { + regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg()); + } else if (int_args < Argument::n_int_register_parameters_c) { + regs[i].set2(INT_ArgReg[int_args++]->as_VMReg()); + } else { + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } + break; + case T_VOID: // Halves of longs and doubles + assert(i != 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "expecting half"); + regs[i].set_bad(); + break; + default: + ShouldNotReachHere(); + } + } + + return stk_args; +} + +// On 64 bit we will store integer like items to the stack as +// 64 bits items (riscv64 abi) even though java would only store +// 32bits for a parameter. On 32bit it will simply be 32 bits +// So this routine will do 32->32 on 32bit and 32->64 on 64bit +static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld(t0, Address(fp, reg2offset_in(src.first()))); + __ sd(t0, Address(sp, reg2offset_out(dst.first()))); + } else { + // stack to reg + __ lw(dst.first()->as_Register(), Address(fp, reg2offset_in(src.first()))); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ sd(src.first()->as_Register(), Address(sp, reg2offset_out(dst.first()))); + } else { + if (dst.first() != src.first()) { + // 32bits extend sign + __ addw(dst.first()->as_Register(), src.first()->as_Register(), zr); + } + } +} + +// An oop arg. Must pass a handle not the oop itself +static void object_move(MacroAssembler* masm, + OopMap* map, + int oop_handle_offset, + int framesize_in_slots, + VMRegPair src, + VMRegPair dst, + bool is_receiver, + int* receiver_offset) { + assert_cond(masm != NULL && map != NULL && receiver_offset != NULL); + // must pass a handle. First figure out the location we use as a handle + Register rHandle = dst.first()->is_stack() ? t1 : dst.first()->as_Register(); + + // See if oop is NULL if it is we need no handle + + if (src.first()->is_stack()) { + + // Oop is already on the stack as an argument + int offset_in_older_frame = src.first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); + map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + framesize_in_slots)); + if (is_receiver) { + *receiver_offset = (offset_in_older_frame + framesize_in_slots) * VMRegImpl::stack_slot_size; + } + + __ ld(t0, Address(fp, reg2offset_in(src.first()))); + __ la(rHandle, Address(fp, reg2offset_in(src.first()))); + // conditionally move a NULL + Label notZero1; + __ bnez(t0, notZero1); + __ mv(rHandle, zr); + __ bind(notZero1); + } else { + + // Oop is in an a register we must store it to the space we reserve + // on the stack for oop_handles and pass a handle if oop is non-NULL + + const Register rOop = src.first()->as_Register(); + int oop_slot = -1; + if (rOop == j_rarg0) { + oop_slot = 0; + } else if (rOop == j_rarg1) { + oop_slot = 1; + } else if (rOop == j_rarg2) { + oop_slot = 2; + } else if (rOop == j_rarg3) { + oop_slot = 3; + } else if (rOop == j_rarg4) { + oop_slot = 4; + } else if (rOop == j_rarg5) { + oop_slot = 5; + } else if (rOop == j_rarg6) { + oop_slot = 6; + } else { + assert(rOop == j_rarg7, "wrong register"); + oop_slot = 7; + } + + oop_slot = oop_slot * VMRegImpl::slots_per_word + oop_handle_offset; + int offset = oop_slot * VMRegImpl::stack_slot_size; + + map->set_oop(VMRegImpl::stack2reg(oop_slot)); + // Store oop in handle area, may be NULL + __ sd(rOop, Address(sp, offset)); + if (is_receiver) { + *receiver_offset = offset; + } + + //rOop maybe the same as rHandle + if (rOop == rHandle) { + Label isZero; + __ beqz(rOop, isZero); + __ la(rHandle, Address(sp, offset)); + __ bind(isZero); + } else { + Label notZero2; + __ la(rHandle, Address(sp, offset)); + __ bnez(rOop, notZero2); + __ mv(rHandle, zr); + __ bind(notZero2); + } + } + + // If arg is on the stack then place it otherwise it is already in correct reg. + if (dst.first()->is_stack()) { + __ sd(rHandle, Address(sp, reg2offset_out(dst.first()))); + } +} + +// A float arg may have to do float reg int reg conversion +static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert(src.first()->is_stack() && dst.first()->is_stack() || + src.first()->is_reg() && dst.first()->is_reg() || src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); + assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + __ lwu(t0, Address(fp, reg2offset_in(src.first()))); + __ sw(t0, Address(sp, reg2offset_out(dst.first()))); + } else if (dst.first()->is_Register()) { + __ lwu(dst.first()->as_Register(), Address(fp, reg2offset_in(src.first()))); + } else { + ShouldNotReachHere(); + } + } else if (src.first() != dst.first()) { + if (src.is_single_phys_reg() && dst.is_single_phys_reg()) { + __ fmv_s(dst.first()->as_FloatRegister(), src.first()->as_FloatRegister()); + } else { + ShouldNotReachHere(); + } + } +} + +// A long move +static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld(t0, Address(fp, reg2offset_in(src.first()))); + __ sd(t0, Address(sp, reg2offset_out(dst.first()))); + } else { + // stack to reg + __ ld(dst.first()->as_Register(), Address(fp, reg2offset_in(src.first()))); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ sd(src.first()->as_Register(), Address(sp, reg2offset_out(dst.first()))); + } else { + if (dst.first() != src.first()) { + __ mv(dst.first()->as_Register(), src.first()->as_Register()); + } + } +} + +// A double move +static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert(src.first()->is_stack() && dst.first()->is_stack() || + src.first()->is_reg() && dst.first()->is_reg() || src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); + assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + __ ld(t0, Address(fp, reg2offset_in(src.first()))); + __ sd(t0, Address(sp, reg2offset_out(dst.first()))); + } else if (dst.first()-> is_Register()) { + __ ld(dst.first()->as_Register(), Address(fp, reg2offset_in(src.first()))); + } else { + ShouldNotReachHere(); + } + } else if (src.first() != dst.first()) { + if (src.is_single_phys_reg() && dst.is_single_phys_reg()) { + __ fmv_d(dst.first()->as_FloatRegister(), src.first()->as_FloatRegister()); + } else { + ShouldNotReachHere(); + } + } +} + +void SharedRuntime::save_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { + assert_cond(masm != NULL); + // We always ignore the frame_slots arg and just use the space just below frame pointer + // which by this time is free to use + switch (ret_type) { + case T_FLOAT: + __ fsw(f10, Address(fp, -3 * wordSize)); + break; + case T_DOUBLE: + __ fsd(f10, Address(fp, -3 * wordSize)); + break; + case T_VOID: break; + default: { + __ sd(x10, Address(fp, -3 * wordSize)); + } + } +} + +void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { + assert_cond(masm != NULL); + // We always ignore the frame_slots arg and just use the space just below frame pointer + // which by this time is free to use + switch (ret_type) { + case T_FLOAT: + __ flw(f10, Address(fp, -3 * wordSize)); + break; + case T_DOUBLE: + __ fld(f10, Address(fp, -3 * wordSize)); + break; + case T_VOID: break; + default: { + __ ld(x10, Address(fp, -3 * wordSize)); + } + } +} + +static void save_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) { + assert_cond(masm != NULL && args != NULL); + RegSet x; + for ( int i = first_arg ; i < arg_count ; i++ ) { + if (args[i].first()->is_Register()) { + x = x + args[i].first()->as_Register(); + } else if (args[i].first()->is_FloatRegister()) { + __ addi(sp, sp, -2 * wordSize); + __ fsd(args[i].first()->as_FloatRegister(), Address(sp, 0)); + } + } + __ push_reg(x, sp); +} + +static void restore_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) { + assert_cond(masm != NULL && args != NULL); + RegSet x; + for ( int i = first_arg ; i < arg_count ; i++ ) { + if (args[i].first()->is_Register()) { + x = x + args[i].first()->as_Register(); + } else { + ; + } + } + __ pop_reg(x, sp); + for ( int i = arg_count - 1 ; i >= first_arg ; i-- ) { + if (args[i].first()->is_Register()) { + ; + } else if (args[i].first()->is_FloatRegister()) { + __ fld(args[i].first()->as_FloatRegister(), Address(sp, 0)); + __ add(sp, sp, 2 * wordSize); + } + } +} + +static void rt_call(MacroAssembler* masm, address dest) { + assert_cond(masm != NULL); + CodeBlob *cb = CodeCache::find_blob(dest); + if (cb) { + __ far_call(RuntimeAddress(dest)); + } else { + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(dest), offset); + __ jalr(x1, t0, offset); + } +} + +static void verify_oop_args(MacroAssembler* masm, + const methodHandle& method, + const BasicType* sig_bt, + const VMRegPair* regs) { + const Register temp_reg = x9; // not part of any compiled calling seq + if (VerifyOops) { + for (int i = 0; i < method->size_of_parameters(); i++) { + if (sig_bt[i] == T_OBJECT || + sig_bt[i] == T_ARRAY) { + VMReg r = regs[i].first(); + assert(r->is_valid(), "bad oop arg"); + if (r->is_stack()) { + __ ld(temp_reg, Address(sp, r->reg2stack() * VMRegImpl::stack_slot_size)); + __ verify_oop(temp_reg); + } else { + __ verify_oop(r->as_Register()); + } + } + } + } +} + +static void gen_special_dispatch(MacroAssembler* masm, + const methodHandle& method, + const BasicType* sig_bt, + const VMRegPair* regs) { + verify_oop_args(masm, method, sig_bt, regs); + vmIntrinsics::ID iid = method->intrinsic_id(); + + // Now write the args into the outgoing interpreter space + bool has_receiver = false; + Register receiver_reg = noreg; + int member_arg_pos = -1; + Register member_reg = noreg; + int ref_kind = MethodHandles::signature_polymorphic_intrinsic_ref_kind(iid); + if (ref_kind != 0) { + member_arg_pos = method->size_of_parameters() - 1; // trailing MemberName argument + member_reg = x9; // known to be free at this point + has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); + } else if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { + has_receiver = true; + } else { + fatal("unexpected intrinsic id %d", vmIntrinsics::as_int(iid)); + } + + if (member_reg != noreg) { + // Load the member_arg into register, if necessary. + SharedRuntime::check_member_name_argument_is_last_argument(method, sig_bt, regs); + VMReg r = regs[member_arg_pos].first(); + if (r->is_stack()) { + __ ld(member_reg, Address(sp, r->reg2stack() * VMRegImpl::stack_slot_size)); + } else { + // no data motion is needed + member_reg = r->as_Register(); + } + } + + if (has_receiver) { + // Make sure the receiver is loaded into a register. + assert(method->size_of_parameters() > 0, "oob"); + assert(sig_bt[0] == T_OBJECT, "receiver argument must be an object"); + VMReg r = regs[0].first(); + assert(r->is_valid(), "bad receiver arg"); + if (r->is_stack()) { + // Porting note: This assumes that compiled calling conventions always + // pass the receiver oop in a register. If this is not true on some + // platform, pick a temp and load the receiver from stack. + fatal("receiver always in a register"); + receiver_reg = x12; // known to be free at this point + __ ld(receiver_reg, Address(sp, r->reg2stack() * VMRegImpl::stack_slot_size)); + } else { + // no data motion is needed + receiver_reg = r->as_Register(); + } + } + + // Figure out which address we are really jumping to: + MethodHandles::generate_method_handle_dispatch(masm, iid, + receiver_reg, member_reg, /*for_compiler_entry:*/ true); +} + +// --------------------------------------------------------------------------- +// Generate a native wrapper for a given method. The method takes arguments +// in the Java compiled code convention, marshals them to the native +// convention (handlizes oops, etc), transitions to native, makes the call, +// returns to java state (possibly blocking), unhandlizes any result and +// returns. +// +// Critical native functions are a shorthand for the use of +// GetPrimtiveArrayCritical and disallow the use of any other JNI +// functions. The wrapper is expected to unpack the arguments before +// passing them to the callee and perform checks before and after the +// native call to ensure that they GCLocker +// lock_critical/unlock_critical semantics are followed. Some other +// parts of JNI setup are skipped like the tear down of the JNI handle +// block and the check for pending exceptions it's impossible for them +// to be thrown. +// +// They are roughly structured like this: +// if (GCLocker::needs_gc()) SharedRuntime::block_for_jni_critical() +// tranistion to thread_in_native +// unpack arrray arguments and call native entry point +// check for safepoint in progress +// check if any thread suspend flags are set +// call into JVM and possible unlock the JNI critical +// if a GC was suppressed while in the critical native. +// transition back to thread_in_Java +// return to caller +// +nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, + const methodHandle& method, + int compile_id, + BasicType* in_sig_bt, + VMRegPair* in_regs, + BasicType ret_type) { + if (method->is_method_handle_intrinsic()) { + vmIntrinsics::ID iid = method->intrinsic_id(); + intptr_t start = (intptr_t)__ pc(); + int vep_offset = ((intptr_t)__ pc()) - start; + + // First instruction must be a nop as it may need to be patched on deoptimisation + __ nop(); + gen_special_dispatch(masm, + method, + in_sig_bt, + in_regs); + int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period + __ flush(); + int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually + return nmethod::new_native_nmethod(method, + compile_id, + masm->code(), + vep_offset, + frame_complete, + stack_slots / VMRegImpl::slots_per_word, + in_ByteSize(-1), + in_ByteSize(-1), + (OopMapSet*)NULL); + } + address native_func = method->native_function(); + assert(native_func != NULL, "must have function"); + + // An OopMap for lock (and class if static) + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + intptr_t start = (intptr_t)__ pc(); + + // We have received a description of where all the java arg are located + // on entry to the wrapper. We need to convert these args to where + // the jni function will expect them. To figure out where they go + // we convert the java signature to a C signature by inserting + // the hidden arguments as arg[0] and possibly arg[1] (static method) + + const int total_in_args = method->size_of_parameters(); + int total_c_args = total_in_args + (method->is_static() ? 2 : 1); + + BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + BasicType* in_elem_bt = NULL; + + int argc = 0; + out_sig_bt[argc++] = T_ADDRESS; + if (method->is_static()) { + out_sig_bt[argc++] = T_OBJECT; + } + + for (int i = 0; i < total_in_args ; i++) { + out_sig_bt[argc++] = in_sig_bt[i]; + } + + // Now figure out where the args must be stored and how much stack space + // they require. + int out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); + + // Compute framesize for the wrapper. We need to handlize all oops in + // incoming registers + + // Calculate the total number of stack slots we will need. + + // First count the abi requirement plus all of the outgoing args + int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; + + // Now the space for the inbound oop handle area + int total_save_slots = 8 * VMRegImpl::slots_per_word; // 8 arguments passed in registers + + int oop_handle_offset = stack_slots; + stack_slots += total_save_slots; + + // Now any space we need for handlizing a klass if static method + + int klass_slot_offset = 0; + int klass_offset = -1; + int lock_slot_offset = 0; + bool is_static = false; + + if (method->is_static()) { + klass_slot_offset = stack_slots; + stack_slots += VMRegImpl::slots_per_word; + klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; + is_static = true; + } + + // Plus a lock if needed + + if (method->is_synchronized()) { + lock_slot_offset = stack_slots; + stack_slots += VMRegImpl::slots_per_word; + } + + // Now a place (+2) to save return values or temp during shuffling + // + 4 for return address (which we own) and saved fp + stack_slots += 6; + + // Ok The space we have allocated will look like: + // + // + // FP-> | | + // | 2 slots (ra) | + // | 2 slots (fp) | + // |---------------------| + // | 2 slots for moves | + // |---------------------| + // | lock box (if sync) | + // |---------------------| <- lock_slot_offset + // | klass (if static) | + // |---------------------| <- klass_slot_offset + // | oopHandle area | + // |---------------------| <- oop_handle_offset (8 java arg registers) + // | outbound memory | + // | based arguments | + // | | + // |---------------------| + // | | + // SP-> | out_preserved_slots | + // + // + + + // Now compute actual number of stack words we need rounding to make + // stack properly aligned. + stack_slots = align_up(stack_slots, StackAlignmentInSlots); + + int stack_size = stack_slots * VMRegImpl::stack_slot_size; + + // First thing make an ic check to see if we should even be here + + // We are free to use all registers as temps without saving them and + // restoring them except fp. fp is the only callee save register + // as far as the interpreter and the compiler(s) are concerned. + + + const Register ic_reg = t1; + const Register receiver = j_rarg0; + + Label hit; + Label exception_pending; + + assert_different_registers(ic_reg, receiver, t0); + __ verify_oop(receiver); + __ cmp_klass(receiver, ic_reg, t0, hit); + + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + + // Verified entry point must be aligned + __ align(8); + + __ bind(hit); + + int vep_offset = ((intptr_t)__ pc()) - start; + + // If we have to make this method not-entrant we'll overwrite its + // first instruction with a jump. + __ nop(); + + if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) { + Label L_skip_barrier; + __ mov_metadata(t1, method->method_holder()); // InstanceKlass* + __ clinit_barrier(t1, t0, &L_skip_barrier); + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + + __ bind(L_skip_barrier); + } + + // Generate stack overflow check + __ bang_stack_with_offset(checked_cast(StackOverflow::stack_shadow_zone_size())); + + // Generate a new frame for the wrapper. + __ enter(); + // -2 because return address is already present and so is saved fp + __ sub(sp, sp, stack_size - 2 * wordSize); + + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + assert_cond(bs != NULL); + bs->nmethod_entry_barrier(masm); + + // Frame is now completed as far as size and linkage. + int frame_complete = ((intptr_t)__ pc()) - start; + + // We use x18 as the oop handle for the receiver/klass + // It is callee save so it survives the call to native + + const Register oop_handle_reg = x18; + + // + // We immediately shuffle the arguments so that any vm call we have to + // make from here on out (sync slow path, jvmti, etc.) we will have + // captured the oops from our caller and have a valid oopMap for + // them. + + // ----------------- + // The Grand Shuffle + + // The Java calling convention is either equal (linux) or denser (win64) than the + // c calling convention. However the because of the jni_env argument the c calling + // convention always has at least one more (and two for static) arguments than Java. + // Therefore if we move the args from java -> c backwards then we will never have + // a register->register conflict and we don't have to build a dependency graph + // and figure out how to break any cycles. + // + + // Record esp-based slot for receiver on stack for non-static methods + int receiver_offset = -1; + + // This is a trick. We double the stack slots so we can claim + // the oops in the caller's frame. Since we are sure to have + // more args than the caller doubling is enough to make + // sure we can capture all the incoming oop args from the + // caller. + // + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + assert_cond(map != NULL); + + int float_args = 0; + int int_args = 0; + +#ifdef ASSERT + bool reg_destroyed[RegisterImpl::number_of_registers]; + bool freg_destroyed[FloatRegisterImpl::number_of_registers]; + for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) { + reg_destroyed[r] = false; + } + for ( int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++ ) { + freg_destroyed[f] = false; + } + +#endif /* ASSERT */ + + // For JNI natives the incoming and outgoing registers are offset upwards. + GrowableArray arg_order(2 * total_in_args); + VMRegPair tmp_vmreg; + tmp_vmreg.set2(x9->as_VMReg()); + + for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) { + arg_order.push(i); + arg_order.push(c_arg); + } + + int temploc = -1; + for (int ai = 0; ai < arg_order.length(); ai += 2) { + int i = arg_order.at(ai); + int c_arg = arg_order.at(ai + 1); + __ block_comment(err_msg("mv %d -> %d", i, c_arg)); + assert(c_arg != -1 && i != -1, "wrong order"); +#ifdef ASSERT + if (in_regs[i].first()->is_Register()) { + assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!"); + } else if (in_regs[i].first()->is_FloatRegister()) { + assert(!freg_destroyed[in_regs[i].first()->as_FloatRegister()->encoding()], "destroyed reg!"); + } + if (out_regs[c_arg].first()->is_Register()) { + reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true; + } else if (out_regs[c_arg].first()->is_FloatRegister()) { + freg_destroyed[out_regs[c_arg].first()->as_FloatRegister()->encoding()] = true; + } +#endif /* ASSERT */ + switch (in_sig_bt[i]) { + case T_ARRAY: + case T_OBJECT: + object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], + ((i == 0) && (!is_static)), + &receiver_offset); + int_args++; + break; + case T_VOID: + break; + + case T_FLOAT: + float_move(masm, in_regs[i], out_regs[c_arg]); + float_args++; + break; + + case T_DOUBLE: + assert( i + 1 < total_in_args && + in_sig_bt[i + 1] == T_VOID && + out_sig_bt[c_arg + 1] == T_VOID, "bad arg list"); + double_move(masm, in_regs[i], out_regs[c_arg]); + float_args++; + break; + + case T_LONG : + long_move(masm, in_regs[i], out_regs[c_arg]); + int_args++; + break; + + case T_ADDRESS: + assert(false, "found T_ADDRESS in java args"); + break; + + default: + move32_64(masm, in_regs[i], out_regs[c_arg]); + int_args++; + } + } + + // point c_arg at the first arg that is already loaded in case we + // need to spill before we call out + int c_arg = total_c_args - total_in_args; + + // Pre-load a static method's oop into c_rarg1. + if (method->is_static()) { + + // load oop into a register + __ movoop(c_rarg1, + JNIHandles::make_local(method->method_holder()->java_mirror()), + /*immediate*/true); + + // Now handlize the static class mirror it's known not-null. + __ sd(c_rarg1, Address(sp, klass_offset)); + map->set_oop(VMRegImpl::stack2reg(klass_slot_offset)); + + // Now get the handle + __ la(c_rarg1, Address(sp, klass_offset)); + // and protect the arg if we must spill + c_arg--; + } + + // Change state to native (we save the return address in the thread, since it might not + // be pushed on the stack when we do a stack traversal). + // We use the same pc/oopMap repeatedly when we call out + + Label native_return; + __ set_last_Java_frame(sp, noreg, native_return, t0); + + Label dtrace_method_entry, dtrace_method_entry_done; + { + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address)&DTraceMethodProbes), offset); + __ lbu(t0, Address(t0, offset)); + __ addw(t0, t0, zr); + __ bnez(t0, dtrace_method_entry); + __ bind(dtrace_method_entry_done); + } + + // RedefineClasses() tracing support for obsolete method entry + if (log_is_enabled(Trace, redefine, class, obsolete)) { + // protect the args we've loaded + save_args(masm, total_c_args, c_arg, out_regs); + __ mov_metadata(c_rarg1, method()); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), + xthread, c_rarg1); + restore_args(masm, total_c_args, c_arg, out_regs); + } + + // Lock a synchronized method + + // Register definitions used by locking and unlocking + + const Register swap_reg = x10; + const Register obj_reg = x9; // Will contain the oop + const Register lock_reg = x30; // Address of compiler lock object (BasicLock) + const Register old_hdr = x30; // value of old header at unlock time + const Register tmp = ra; + + Label slow_path_lock; + Label lock_done; + + if (method->is_synchronized()) { + + const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); + + // Get the handle (the 2nd argument) + __ mv(oop_handle_reg, c_rarg1); + + // Get address of the box + + __ la(lock_reg, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + + // Load the oop from the handle + __ ld(obj_reg, Address(oop_handle_reg, 0)); + + if (!UseHeavyMonitors) { + // Load (object->mark() | 1) into swap_reg % x10 + __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ ori(swap_reg, t0, 1); + + // Save (object->mark() | 1) into BasicLock's displaced header + __ sd(swap_reg, Address(lock_reg, mark_word_offset)); + + // src -> dest if dest == x10 else x10 <- dest + { + Label here; + __ cmpxchg_obj_header(x10, lock_reg, obj_reg, t0, lock_done, /*fallthrough*/NULL); + } + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) sp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - sp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg + + __ sub(swap_reg, swap_reg, sp); + __ andi(swap_reg, swap_reg, 3 - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + __ sd(swap_reg, Address(lock_reg, mark_word_offset)); + __ bnez(swap_reg, slow_path_lock); + } else { + __ j(slow_path_lock); + } + + // Slow path will re-enter here + __ bind(lock_done); + } + + + // Finally just about ready to make the JNI call + + // get JNIEnv* which is first argument to native + __ la(c_rarg0, Address(xthread, in_bytes(JavaThread::jni_environment_offset()))); + + // Now set thread in native + __ la(t1, Address(xthread, JavaThread::thread_state_offset())); + __ mv(t0, _thread_in_native); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sw(t0, Address(t1)); + + rt_call(masm, native_func); + + __ bind(native_return); + + intptr_t return_pc = (intptr_t) __ pc(); + oop_maps->add_gc_map(return_pc - start, map); + + // Unpack native results. + if (ret_type != T_OBJECT && ret_type != T_ARRAY) { + __ cast_primitive_type(ret_type, x10); + } + + Label safepoint_in_progress, safepoint_in_progress_done; + Label after_transition; + + // Switch thread to "native transition" state before reading the synchronization state. + // This additional state is necessary because reading and testing the synchronization + // state is not atomic w.r.t. GC, as this scenario demonstrates: + // Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted. + // VM thread changes sync state to synchronizing and suspends threads for GC. + // Thread A is resumed to finish this native method, but doesn't block here since it + // didn't see any synchronization is progress, and escapes. + __ mv(t0, _thread_in_native_trans); + + __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + + // Force this write out before the read below + __ membar(MacroAssembler::AnyAny); + + // check for safepoint operation in progress and/or pending suspend requests + { + // We need an acquire here to ensure that any subsequent load of the + // global SafepointSynchronize::_state flag is ordered after this load + // of the thread-local polling word. We don't want this poll to + // return false (i.e. not safepointing) and a later poll of the global + // SafepointSynchronize::_state spuriously to return true. + // This is to avoid a race when we're in a native->Java transition + // racing the code which wakes up from a safepoint. + + __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); + __ bnez(t0, safepoint_in_progress); + __ bind(safepoint_in_progress_done); + } + + // change thread state + __ la(t1, Address(xthread, JavaThread::thread_state_offset())); + __ mv(t0, _thread_in_Java); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sw(t0, Address(t1)); + __ bind(after_transition); + + Label reguard; + Label reguard_done; + __ lbu(t0, Address(xthread, JavaThread::stack_guard_state_offset())); + __ mv(t1, StackOverflow::stack_guard_yellow_reserved_disabled); + __ beq(t0, t1, reguard); + __ bind(reguard_done); + + // native result if any is live + + // Unlock + Label unlock_done; + Label slow_path_unlock; + if (method->is_synchronized()) { + + // Get locked oop from the handle we passed to jni + __ ld(obj_reg, Address(oop_handle_reg, 0)); + + Label done; + + if (!UseHeavyMonitors) { + // Simple recursive lock? + __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + __ beqz(t0, done); + } + + + // Must save x10 if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } + + if (!UseHeavyMonitors) { + // get address of the stack lock + __ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + // get old displaced header + __ ld(old_hdr, Address(x10, 0)); + + // Atomic swap old header if oop still contains the stack lock + Label succeed; + __ cmpxchg_obj_header(x10, old_hdr, obj_reg, t0, succeed, &slow_path_unlock); + __ bind(succeed); + } else { + __ j(slow_path_unlock); + } + + // slow path re-enters here + __ bind(unlock_done); + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + restore_native_result(masm, ret_type, stack_slots); + } + + __ bind(done); + } + + Label dtrace_method_exit, dtrace_method_exit_done; + { + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address)&DTraceMethodProbes), offset); + __ lbu(t0, Address(t0, offset)); + __ bnez(t0, dtrace_method_exit); + __ bind(dtrace_method_exit_done); + } + + __ reset_last_Java_frame(false); + + // Unbox oop result, e.g. JNIHandles::resolve result. + if (is_reference_type(ret_type)) { + __ resolve_jobject(x10, xthread, t1); + } + + if (CheckJNICalls) { + // clear_pending_jni_exception_check + __ sd(zr, Address(xthread, JavaThread::pending_jni_exception_check_fn_offset())); + } + + // reset handle block + __ ld(x12, Address(xthread, JavaThread::active_handles_offset())); + __ sd(zr, Address(x12, JNIHandleBlock::top_offset_in_bytes())); + + __ leave(); + + // Any exception pending? + __ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + __ bnez(t0, exception_pending); + + // We're done + __ ret(); + + // Unexpected paths are out of line and go here + + // forward the exception + __ bind(exception_pending); + + // and forward the exception + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + + // Slow path locking & unlocking + if (method->is_synchronized()) { + + __ block_comment("Slow path lock {"); + __ bind(slow_path_lock); + + // has last_Java_frame setup. No exceptions so do vanilla call not call_VM + // args are (oop obj, BasicLock* lock, JavaThread* thread) + + // protect the args we've loaded + save_args(masm, total_c_args, c_arg, out_regs); + + __ mv(c_rarg0, obj_reg); + __ mv(c_rarg1, lock_reg); + __ mv(c_rarg2, xthread); + + // Not a leaf but we have last_Java_frame setup as we want + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), 3); + restore_args(masm, total_c_args, c_arg, out_regs); + +#ifdef ASSERT + { Label L; + __ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + __ beqz(t0, L); + __ stop("no pending exception allowed on exit from monitorenter"); + __ bind(L); + } +#endif + __ j(lock_done); + + __ block_comment("} Slow path lock"); + + __ block_comment("Slow path unlock {"); + __ bind(slow_path_unlock); + + if (ret_type == T_FLOAT || ret_type == T_DOUBLE) { + save_native_result(masm, ret_type, stack_slots); + } + + __ mv(c_rarg2, xthread); + __ la(c_rarg1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + __ mv(c_rarg0, obj_reg); + + // Save pending exception around call to VM (which contains an EXCEPTION_MARK) + // NOTE that obj_reg == x9 currently + __ ld(x9, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + __ sd(zr, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + + rt_call(masm, CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C)); + +#ifdef ASSERT + { + Label L; + __ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + __ beqz(t0, L); + __ stop("no pending exception allowed on exit complete_monitor_unlocking_C"); + __ bind(L); + } +#endif /* ASSERT */ + + __ sd(x9, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + + if (ret_type == T_FLOAT || ret_type == T_DOUBLE) { + restore_native_result(masm, ret_type, stack_slots); + } + __ j(unlock_done); + + __ block_comment("} Slow path unlock"); + + } // synchronized + + // SLOW PATH Reguard the stack if needed + + __ bind(reguard); + save_native_result(masm, ret_type, stack_slots); + rt_call(masm, CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); + restore_native_result(masm, ret_type, stack_slots); + // and continue + __ j(reguard_done); + + // SLOW PATH safepoint + { + __ block_comment("safepoint {"); + __ bind(safepoint_in_progress); + + // Don't use call_VM as it will see a possible pending exception and forward it + // and never return here preventing us from clearing _last_native_pc down below. + // + save_native_result(masm, ret_type, stack_slots); + __ mv(c_rarg0, xthread); +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)), offset); + __ jalr(x1, t0, offset); + + // Restore any method result value + restore_native_result(masm, ret_type, stack_slots); + + __ j(safepoint_in_progress_done); + __ block_comment("} safepoint"); + } + + // SLOW PATH dtrace support + { + __ block_comment("dtrace entry {"); + __ bind(dtrace_method_entry); + + // We have all of the arguments setup at this point. We must not touch any register + // argument registers at this point (what if we save/restore them there are no oop? + + save_args(masm, total_c_args, c_arg, out_regs); + __ mov_metadata(c_rarg1, method()); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), + xthread, c_rarg1); + restore_args(masm, total_c_args, c_arg, out_regs); + __ j(dtrace_method_entry_done); + __ block_comment("} dtrace entry"); + } + + { + __ block_comment("dtrace exit {"); + __ bind(dtrace_method_exit); + save_native_result(masm, ret_type, stack_slots); + __ mov_metadata(c_rarg1, method()); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), + xthread, c_rarg1); + restore_native_result(masm, ret_type, stack_slots); + __ j(dtrace_method_exit_done); + __ block_comment("} dtrace exit"); + } + + __ flush(); + + nmethod *nm = nmethod::new_native_nmethod(method, + compile_id, + masm->code(), + vep_offset, + frame_complete, + stack_slots / VMRegImpl::slots_per_word, + (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), + in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), + oop_maps); + assert(nm != NULL, "create native nmethod fail!"); + return nm; +} + +// this function returns the adjust size (in number of words) to a c2i adapter +// activation for use during deoptimization +int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { + assert(callee_locals >= callee_parameters, + "test and remove; got more parms than locals"); + if (callee_locals < callee_parameters) { + return 0; // No adjustment for negative locals + } + int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords; + // diff is counted in stack words + return align_up(diff, 2); +} + +//------------------------------generate_deopt_blob---------------------------- +void SharedRuntime::generate_deopt_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + int pad = 0; + CodeBuffer buffer("deopt_blob", 2048 + pad, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + int frame_size_in_words = -1; + OopMap* map = NULL; + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(masm != NULL && oop_maps != NULL); + RegisterSaver reg_saver(COMPILER2_OR_JVMCI != 0); + + // ------------- + // This code enters when returning to a de-optimized nmethod. A return + // address has been pushed on the the stack, and return values are in + // registers. + // If we are doing a normal deopt then we were called from the patched + // nmethod from the point we returned to the nmethod. So the return + // address on the stack is wrong by NativeCall::instruction_size + // We will adjust the value so it looks like we have the original return + // address on the stack (like when we eagerly deoptimized). + // In the case of an exception pending when deoptimizing, we enter + // with a return address on the stack that points after the call we patched + // into the exception handler. We have the following register state from, + // e.g., the forward exception stub (see stubGenerator_riscv.cpp). + // x10: exception oop + // x9: exception handler + // x13: throwing pc + // So in this case we simply jam x13 into the useless return address and + // the stack looks just like we want. + // + // At this point we need to de-opt. We save the argument return + // registers. We call the first C routine, fetch_unroll_info(). This + // routine captures the return values and returns a structure which + // describes the current frame size and the sizes of all replacement frames. + // The current frame is compiled code and may contain many inlined + // functions, each with their own JVM state. We pop the current frame, then + // push all the new frames. Then we call the C routine unpack_frames() to + // populate these frames. Finally unpack_frames() returns us the new target + // address. Notice that callee-save registers are BLOWN here; they have + // already been captured in the vframeArray at the time the return PC was + // patched. + address start = __ pc(); + Label cont; + + // Prolog for non exception case! + + // Save everything in sight. + map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); + + // Normal deoptimization. Save exec mode for unpack_frames. + __ mvw(xcpool, Deoptimization::Unpack_deopt); // callee-saved + __ j(cont); + + int reexecute_offset = __ pc() - start; + + // Reexecute case + // return address is the pc describes what bci to do re-execute at + + // No need to update map as each call to save_live_registers will produce identical oopmap + (void) reg_saver.save_live_registers(masm, 0, &frame_size_in_words); + + __ mvw(xcpool, Deoptimization::Unpack_reexecute); // callee-saved + __ j(cont); + + int exception_offset = __ pc() - start; + + // Prolog for exception case + + // all registers are dead at this entry point, except for x10, and + // x13 which contain the exception oop and exception pc + // respectively. Set them in TLS and fall thru to the + // unpack_with_exception_in_tls entry point. + + __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); + __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); + + int exception_in_tls_offset = __ pc() - start; + + // new implementation because exception oop is now passed in JavaThread + + // Prolog for exception case + // All registers must be preserved because they might be used by LinearScan + // Exceptiop oop and throwing PC are passed in JavaThread + // tos: stack at point of call to method that threw the exception (i.e. only + // args are on the stack, no return address) + + // The return address pushed by save_live_registers will be patched + // later with the throwing pc. The correct value is not available + // now because loading it from memory would destroy registers. + + // NB: The SP at this point must be the SP of the method that is + // being deoptimized. Deoptimization assumes that the frame created + // here by save_live_registers is immediately below the method's SP. + // This is a somewhat fragile mechanism. + + // Save everything in sight. + map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); + + // Now it is safe to overwrite any register + + // Deopt during an exception. Save exec mode for unpack_frames. + __ li(xcpool, Deoptimization::Unpack_exception); // callee-saved + + // load throwing pc from JavaThread and patch it as the return address + // of the current frame. Then clear the field in JavaThread + + __ ld(x13, Address(xthread, JavaThread::exception_pc_offset())); + __ sd(x13, Address(fp, frame::return_addr_offset * wordSize)); + __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); + +#ifdef ASSERT + // verify that there is really an exception oop in JavaThread + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ verify_oop(x10); + + // verify that there is no pending exception + Label no_pending_exception; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ beqz(t0, no_pending_exception); + __ stop("must not have pending exception here"); + __ bind(no_pending_exception); +#endif + + __ bind(cont); + + // Call C code. Need thread and this frame, but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. + // + // UnrollBlock* fetch_unroll_info(JavaThread* thread) + + // fetch_unroll_info needs to call last_java_frame(). + + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, t0); +#ifdef ASSERT + { + Label L; + __ ld(t0, Address(xthread, + JavaThread::last_Java_fp_offset())); + __ beqz(t0, L); + __ stop("SharedRuntime::generate_deopt_blob: last_Java_fp not cleared"); + __ bind(L); + } +#endif // ASSERT + __ mv(c_rarg0, xthread); + __ mv(c_rarg1, xcpool); + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)), offset); + __ jalr(x1, t0, offset); + __ bind(retaddr); + + // Need to have an oopmap that tells fetch_unroll_info where to + // find any register it might need. + oop_maps->add_gc_map(__ pc() - start, map); + + __ reset_last_Java_frame(false); + + // Load UnrollBlock* into x15 + __ mv(x15, x10); + + __ lwu(xcpool, Address(x15, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes())); + Label noException; + __ li(t0, Deoptimization::Unpack_exception); + __ bne(xcpool, t0, noException); // Was exception pending? + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ ld(x13, Address(xthread, JavaThread::exception_pc_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); + + __ verify_oop(x10); + + // Overwrite the result registers with the exception results. + __ sd(x10, Address(sp, reg_saver.reg_offset_in_bytes(x10))); + + __ bind(noException); + + // Only register save data is on the stack. + // Now restore the result registers. Everything else is either dead + // or captured in the vframeArray. + + // Restore fp result register + __ fld(f10, Address(sp, reg_saver.freg_offset_in_bytes(f10))); + // Restore integer result register + __ ld(x10, Address(sp, reg_saver.reg_offset_in_bytes(x10))); + + // Pop all of the register save area off the stack + __ add(sp, sp, frame_size_in_words * wordSize); + + // All of the register save area has been popped of the stack. Only the + // return address remains. + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + // + // Note: by leaving the return address of self-frame on the stack + // and using the size of frame 2 to adjust the stack + // when we are done the return to frame 3 will still be on the stack. + + // Pop deoptimized frame + __ lwu(x12, Address(x15, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset_in_bytes())); + __ sub(x12, x12, 2 * wordSize); + __ add(sp, sp, x12); + __ ld(fp, Address(sp, 0)); + __ ld(ra, Address(sp, wordSize)); + __ addi(sp, sp, 2 * wordSize); + // RA should now be the return address to the caller (3) + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ lwu(x9, Address(x15, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); + __ bang_stack_size(x9, x12); +#endif + // Load address of array of frame pcs into x12 + __ ld(x12, Address(x15, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); + + // Load address of array of frame sizes into x14 + __ ld(x14, Address(x15, Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes())); + + // Load counter into x13 + __ lwu(x13, Address(x15, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); + + // Now adjust the caller's stack to make up for the extra locals + // but record the original sp so that we can save it in the skeletal interpreter + // frame and the stack walking of interpreter_sender will get the unextended sp + // value and not the "real" sp value. + + const Register sender_sp = x16; + + __ mv(sender_sp, sp); + __ lwu(x9, Address(x15, + Deoptimization::UnrollBlock:: + caller_adjustment_offset_in_bytes())); + __ sub(sp, sp, x9); + + // Push interpreter frames in a loop + __ li(t0, 0xDEADDEAD); // Make a recognizable pattern + __ mv(t1, t0); + Label loop; + __ bind(loop); + __ ld(x9, Address(x14, 0)); // Load frame size + __ addi(x14, x14, wordSize); + __ sub(x9, x9, 2 * wordSize); // We'll push pc and fp by hand + __ ld(ra, Address(x12, 0)); // Load pc + __ addi(x12, x12, wordSize); + __ enter(); // Save old & set new fp + __ sub(sp, sp, x9); // Prolog + // This value is corrected by layout_activation_impl + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ sd(sender_sp, Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable + __ mv(sender_sp, sp); // Pass sender_sp to next frame + __ addi(x13, x13, -1); // Decrement counter + __ bnez(x13, loop); + + // Re-push self-frame + __ ld(ra, Address(x12)); + __ enter(); + + // Allocate a full sized register save area. We subtract 2 because + // enter() just pushed 2 words + __ sub(sp, sp, (frame_size_in_words - 2) * wordSize); + + // Restore frame locals after moving the frame + __ fsd(f10, Address(sp, reg_saver.freg_offset_in_bytes(f10))); + __ sd(x10, Address(sp, reg_saver.reg_offset_in_bytes(x10))); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + // + // void Deoptimization::unpack_frames(JavaThread* thread, int exec_mode) + + // Use fp because the frames look interpreted now + // Don't need the precise return PC here, just precise enough to point into this code blob. + address the_pc = __ pc(); + __ set_last_Java_frame(sp, fp, the_pc, t0); + + __ mv(c_rarg0, xthread); + __ mv(c_rarg1, xcpool); // second arg: exec_mode + offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)), offset); + __ jalr(x1, t0, offset); + + // Set an oopmap for the call site + // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, + new OopMap(frame_size_in_words, 0)); + + // Clear fp AND pc + __ reset_last_Java_frame(true); + + // Collect return values + __ fld(f10, Address(sp, reg_saver.freg_offset_in_bytes(f10))); + __ ld(x10, Address(sp, reg_saver.reg_offset_in_bytes(x10))); + + // Pop self-frame. + __ leave(); // Epilog + + // Jump to interpreter + __ ret(); + + // Make sure all code is generated + masm->flush(); + + _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); + assert(_deopt_blob != NULL, "create deoptimization blob fail!"); + _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); +} + +// Number of stack slots between incoming argument block and the start of +// a new frame. The PROLOG must add this many slots to the stack. The +// EPILOG must remove this many slots. +// RISCV needs two words for RA (return address) and FP (frame pointer). +uint SharedRuntime::in_preserve_stack_slots() { + return 2 * VMRegImpl::slots_per_word; +} + +uint SharedRuntime::out_preserve_stack_slots() { + return 0; +} + +#ifdef COMPILER2 +//------------------------------generate_uncommon_trap_blob-------------------- +void SharedRuntime::generate_uncommon_trap_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != NULL); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + address start = __ pc(); + + // Push self-frame. We get here with a return address in RA + // and sp should be 16 byte aligned + // push fp and retaddr by hand + __ addi(sp, sp, -2 * wordSize); + __ sd(ra, Address(sp, wordSize)); + __ sd(fp, Address(sp, 0)); + // we don't expect an arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // compiler left unloaded_class_index in j_rarg0 move to where the + // runtime expects it. + __ addiw(c_rarg1, j_rarg0, 0); + + // we need to set the past SP to the stack pointer of the stub frame + // and the pc to the address where this runtime call will return + // although actually any pc in this code blob will do). + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, t0); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // capture callee-saved registers as well as return values. + // + // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode) + // + // n.b. 3 gp args, 0 fp args, integral return type + + __ mv(c_rarg0, xthread); + __ mvw(c_rarg2, (unsigned)Deoptimization::Unpack_uncommon_trap); + int32_t offset = 0; + __ la_patchable(t0, + RuntimeAddress(CAST_FROM_FN_PTR(address, + Deoptimization::uncommon_trap)), offset); + __ jalr(x1, t0, offset); + __ bind(retaddr); + + // Set an oopmap for the call site + OopMapSet* oop_maps = new OopMapSet(); + OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); + assert_cond(oop_maps != NULL && map != NULL); + + // location of fp is known implicitly by the frame sender code + + oop_maps->add_gc_map(__ pc() - start, map); + + __ reset_last_Java_frame(false); + + // move UnrollBlock* into x14 + __ mv(x14, x10); + +#ifdef ASSERT + { Label L; + __ lwu(t0, Address(x14, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes())); + __ mvw(t1, Deoptimization::Unpack_uncommon_trap); + __ beq(t0, t1, L); + __ stop("SharedRuntime::generate_deopt_blob: last_Java_fp not cleared"); + __ bind(L); + } +#endif + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + + __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog! + + // Pop deoptimized frame (int) + __ lwu(x12, Address(x14, + Deoptimization::UnrollBlock:: + size_of_deoptimized_frame_offset_in_bytes())); + __ sub(x12, x12, 2 * wordSize); + __ add(sp, sp, x12); + __ ld(fp, sp, 0); + __ ld(ra, sp, wordSize); + __ addi(sp, sp, 2 * wordSize); + // RA should now be the return address to the caller (3) frame + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ lwu(x11, Address(x14, + Deoptimization::UnrollBlock:: + total_frame_sizes_offset_in_bytes())); + __ bang_stack_size(x11, x12); +#endif + + // Load address of array of frame pcs into x12 (address*) + __ ld(x12, Address(x14, + Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); + + // Load address of array of frame sizes into x15 (intptr_t*) + __ ld(x15, Address(x14, + Deoptimization::UnrollBlock:: + frame_sizes_offset_in_bytes())); + + // Counter + __ lwu(x13, Address(x14, + Deoptimization::UnrollBlock:: + number_of_frames_offset_in_bytes())); // (int) + + // Now adjust the caller's stack to make up for the extra locals but + // record the original sp so that we can save it in the skeletal + // interpreter frame and the stack walking of interpreter_sender + // will get the unextended sp value and not the "real" sp value. + + const Register sender_sp = t1; // temporary register + + __ lwu(x11, Address(x14, + Deoptimization::UnrollBlock:: + caller_adjustment_offset_in_bytes())); // (int) + __ mv(sender_sp, sp); + __ sub(sp, sp, x11); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ ld(x11, Address(x15, 0)); // Load frame size + __ sub(x11, x11, 2 * wordSize); // We'll push pc and fp by hand + __ ld(ra, Address(x12, 0)); // Save return address + __ enter(); // and old fp & set new fp + __ sub(sp, sp, x11); // Prolog + __ sd(sender_sp, Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable + // This value is corrected by layout_activation_impl + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ mv(sender_sp, sp); // Pass sender_sp to next frame + __ add(x15, x15, wordSize); // Bump array pointer (sizes) + __ add(x12, x12, wordSize); // Bump array pointer (pcs) + __ subw(x13, x13, 1); // Decrement counter + __ bgtz(x13, loop); + __ ld(ra, Address(x12, 0)); // save final return address + // Re-push self-frame + __ enter(); // & old fp & set new fp + + // Use fp because the frames look interpreted now + // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. + // Don't need the precise return PC here, just precise enough to point into this code blob. + address the_pc = __ pc(); + __ set_last_Java_frame(sp, fp, the_pc, t0); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + // + // BasicType unpack_frames(JavaThread* thread, int exec_mode) + // + + // n.b. 2 gp args, 0 fp args, integral return type + + // sp should already be aligned + __ mv(c_rarg0, xthread); + __ mvw(c_rarg1, (unsigned)Deoptimization::Unpack_uncommon_trap); + offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)), offset); + __ jalr(x1, t0, offset); + + // Set an oopmap for the call site + // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + // Clear fp AND pc + __ reset_last_Java_frame(true); + + // Pop self-frame. + __ leave(); // Epilog + + // Jump to interpreter + __ ret(); + + // Make sure all code is generated + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, + SimpleRuntimeFrame::framesize >> 1); +} +#endif // COMPILER2 + +//------------------------------generate_handler_blob------ +// +// Generate a special Compile2Runtime blob that saves all registers, +// and setup oopmap. +// +SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_type) { + ResourceMark rm; + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + OopMap* map = NULL; + + // Allocate space for the code. Setup code generation tools. + CodeBuffer buffer("handler_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != NULL); + + address start = __ pc(); + address call_pc = NULL; + int frame_size_in_words = -1; + bool cause_return = (poll_type == POLL_AT_RETURN); + RegisterSaver reg_saver(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); + + // Save Integer and Float registers. + map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); + + // The following is basically a call_VM. However, we need the precise + // address of the call in order to generate an oopmap. Hence, we do all the + // work outselves. + + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, t0); + + // The return address must always be correct so that frame constructor never + // sees an invalid pc. + + if (!cause_return) { + // overwrite the return address pushed by save_live_registers + // Additionally, x18 is a callee-saved register so we can look at + // it later to determine if someone changed the return address for + // us! + __ ld(x18, Address(xthread, JavaThread::saved_exception_pc_offset())); + __ sd(x18, Address(fp, frame::return_addr_offset * wordSize)); + } + + // Do the call + __ mv(c_rarg0, xthread); + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(call_ptr), offset); + __ jalr(x1, t0, offset); + __ bind(retaddr); + + // Set an oopmap for the call site. This oopmap will map all + // oop-registers and debug-info registers as callee-saved. This + // will allow deoptimization at this safepoint to find all possible + // debug-info recordings, as well as let GC find all oops. + + oop_maps->add_gc_map( __ pc() - start, map); + + Label noException; + + __ reset_last_Java_frame(false); + + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ beqz(t0, noException); + + // Exception pending + + reg_saver.restore_live_registers(masm); + + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + + // No exception case + __ bind(noException); + + Label no_adjust, bail; + if (!cause_return) { + // If our stashed return pc was modified by the runtime we avoid touching it + __ ld(t0, Address(fp, frame::return_addr_offset * wordSize)); + __ bne(x18, t0, no_adjust); + +#ifdef ASSERT + // Verify the correct encoding of the poll we're about to skip. + // See NativeInstruction::is_lwu_to_zr() + __ lwu(t0, Address(x18)); + __ andi(t1, t0, 0b0000011); + __ mv(t2, 0b0000011); + __ bne(t1, t2, bail); // 0-6:0b0000011 + __ srli(t1, t0, 7); + __ andi(t1, t1, 0b00000); + __ bnez(t1, bail); // 7-11:0b00000 + __ srli(t1, t0, 12); + __ andi(t1, t1, 0b110); + __ mv(t2, 0b110); + __ bne(t1, t2, bail); // 12-14:0b110 +#endif + // Adjust return pc forward to step over the safepoint poll instruction + __ add(x18, x18, NativeInstruction::instruction_size); + __ sd(x18, Address(fp, frame::return_addr_offset * wordSize)); + } + + __ bind(no_adjust); + // Normal exit, restore registers and exit. + + reg_saver.restore_live_registers(masm); + __ ret(); + +#ifdef ASSERT + __ bind(bail); + __ stop("Attempting to adjust pc to skip safepoint poll but the return point is not what we expected"); +#endif + + // Make sure all code is generated + masm->flush(); + + // Fill-out other meta info + return SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); +} + +// +// generate_resolve_blob - call resolution (static/virtual/opt-virtual/ic-miss +// +// Generate a stub that calls into vm to find out the proper destination +// of a java call. All the argument registers are live at this point +// but since this is generic code we don't know what they are and the caller +// must do any gc of the args. +// +RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const char* name) { + assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); + + // allocate space for the code + ResourceMark rm; + + CodeBuffer buffer(name, 1000, 512); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != NULL); + + int frame_size_in_words = -1; + RegisterSaver reg_saver(false /* save_vectors */); + + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + OopMap* map = NULL; + + int start = __ offset(); + + map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); + + int frame_complete = __ offset(); + + { + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, t0); + + __ mv(c_rarg0, xthread); + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(destination), offset); + __ jalr(x1, t0, offset); + __ bind(retaddr); + } + + // Set an oopmap for the call site. + // We need this not only for callee-saved registers, but also for volatile + // registers that the compiler might be keeping live across a safepoint. + + oop_maps->add_gc_map( __ offset() - start, map); + + // x10 contains the address we are going to jump to assuming no exception got installed + + // clear last_Java_sp + __ reset_last_Java_frame(false); + // check for pending exceptions + Label pending; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ bnez(t0, pending); + + // get the returned Method* + __ get_vm_result_2(xmethod, xthread); + __ sd(xmethod, Address(sp, reg_saver.reg_offset_in_bytes(xmethod))); + + // x10 is where we want to jump, overwrite t0 which is saved and temporary + __ sd(x10, Address(sp, reg_saver.reg_offset_in_bytes(t0))); + reg_saver.restore_live_registers(masm); + + // We are back the the original state on entry and ready to go. + + __ jr(t0); + + // Pending exception after the safepoint + + __ bind(pending); + + reg_saver.restore_live_registers(masm); + + // exception pending => remove activation and forward to exception handler + + __ sd(zr, Address(xthread, JavaThread::vm_result_offset())); + + __ ld(x10, Address(xthread, Thread::pending_exception_offset())); + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + + // ------------- + // make sure all code is generated + masm->flush(); + + // return the blob + return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); +} + +#ifdef COMPILER2 +RuntimeStub* SharedRuntime::make_native_invoker(address call_target, + int shadow_space_bytes, + const GrowableArray& input_registers, + const GrowableArray& output_registers) { + Unimplemented(); + return nullptr; +} + +//------------------------------generate_exception_blob--------------------------- +// creates exception blob at the end +// Using exception blob, this code is jumped from a compiled method. +// (see emit_exception_handler in riscv.ad file) +// +// Given an exception pc at a call we call into the runtime for the +// handler in this method. This handler might merely restore state +// (i.e. callee save registers) unwind the frame and jump to the +// exception handler for the nmethod if there is no Java level handler +// for the nmethod. +// +// This code is entered with a jmp. +// +// Arguments: +// x10: exception oop +// x13: exception pc +// +// Results: +// x10: exception oop +// x13: exception pc in caller +// destination: exception handler of caller +// +// Note: the exception pc MUST be at a call (precise debug information) +// Registers x10, x13, x12, x14, x15, t0 are not callee saved. +// + +void OptoRuntime::generate_exception_blob() { + assert(!OptoRuntime::is_callee_saved_register(R13_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R10_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R12_num), ""); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("exception_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != NULL); + + // TODO check various assumptions made here + // + // make sure we do so before running this + + address start = __ pc(); + + // push fp and retaddr by hand + // Exception pc is 'return address' for stack walker + __ addi(sp, sp, -2 * wordSize); + __ sd(ra, Address(sp, wordSize)); + __ sd(fp, Address(sp)); + // there are no callee save registers and we don't expect an + // arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // Store exception in Thread object. We cannot pass any arguments to the + // handle_exception call, since we do not want to make any assumption + // about the size of the frame where the exception happened in. + __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); + + // This call does all the hard work. It checks if an exception handler + // exists in the method. + // If so, it returns the handler address. + // If not, it prepares for stack-unwinding, restoring the callee-save + // registers of the frame being removed. + // + // address OptoRuntime::handle_exception_C(JavaThread* thread) + // + // n.b. 1 gp arg, 0 fp args, integral return type + + // the stack should always be aligned + address the_pc = __ pc(); + __ set_last_Java_frame(sp, noreg, the_pc, t0); + __ mv(c_rarg0, xthread); + int32_t offset = 0; + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)), offset); + __ jalr(x1, t0, offset); + + + // handle_exception_C is a special VM call which does not require an explicit + // instruction sync afterwards. + + // Set an oopmap for the call site. This oopmap will only be used if we + // are unwinding the stack. Hence, all locations will be dead. + // Callee-saved registers will be the same as the frame above (i.e., + // handle_exception_stub), since they were restored when we got the + // exception. + + OopMapSet* oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); + + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + __ reset_last_Java_frame(false); + + // Restore callee-saved registers + + // fp is an implicitly saved callee saved register (i.e. the calling + // convention will save restore it in prolog/epilog) Other than that + // there are no callee save registers now that adapter frames are gone. + // and we dont' expect an arg reg save area + __ ld(fp, Address(sp)); + __ ld(x13, Address(sp, wordSize)); + __ addi(sp, sp , 2 * wordSize); + + // x10: exception handler + + // We have a handler in x10 (could be deopt blob). + __ mv(t0, x10); + + // Get the exception oop + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + // Get the exception pc in case we are deoptimized + __ ld(x14, Address(xthread, JavaThread::exception_pc_offset())); +#ifdef ASSERT + __ sd(zr, Address(xthread, JavaThread::exception_handler_pc_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); +#endif + // Clear the exception oop so GC no longer processes it as a root. + __ sd(zr, Address(xthread, JavaThread::exception_oop_offset())); + + // x10: exception oop + // t0: exception handler + // x14: exception pc + // Jump to handler + + __ jr(t0); + + // Make sure all code is generated + masm->flush(); + + // Set exception blob + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); +} +#endif // COMPILER2 diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3fdd04db1b3998acaaed1440ebc84e42fb8e7b1 --- /dev/null +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -0,0 +1,3864 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "compiler/oopMap.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/universe.hpp" +#include "nativeInst_riscv.hpp" +#include "oops/instanceOop.hpp" +#include "oops/method.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif +#if INCLUDE_ZGC +#include "gc/z/zThreadLocalData.hpp" +#endif + +// Declaration and definition of StubGenerator (no .hpp file). +// For a more detailed description of the stub routine structure +// see the comment in stubRoutines.hpp + +#undef __ +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +// Stub Code definitions + +class StubGenerator: public StubCodeGenerator { + private: + +#ifdef PRODUCT +#define inc_counter_np(counter) ((void)0) +#else + void inc_counter_np_(int& counter) { + __ la(t1, ExternalAddress((address)&counter)); + __ lwu(t0, Address(t1, 0)); + __ addiw(t0, t0, 1); + __ sw(t0, Address(t1, 0)); + } +#define inc_counter_np(counter) \ + BLOCK_COMMENT("inc_counter " #counter); \ + inc_counter_np_(counter); +#endif + + // Call stubs are used to call Java from C + // + // Arguments: + // c_rarg0: call wrapper address address + // c_rarg1: result address + // c_rarg2: result type BasicType + // c_rarg3: method Method* + // c_rarg4: (interpreter) entry point address + // c_rarg5: parameters intptr_t* + // c_rarg6: parameter size (in words) int + // c_rarg7: thread Thread* + // + // There is no return from the stub itself as any Java result + // is written to result + // + // we save x1 (ra) as the return PC at the base of the frame and + // link x8 (fp) below it as the frame pointer installing sp (x2) + // into fp. + // + // we save x10-x17, which accounts for all the c arguments. + // + // TODO: strictly do we need to save them all? they are treated as + // volatile by C so could we omit saving the ones we are going to + // place in global registers (thread? method?) or those we only use + // during setup of the Java call? + // + // we don't need to save x5 which C uses as an indirect result location + // return register. + // + // we don't need to save x6-x7 and x28-x31 which both C and Java treat as + // volatile + // + // we save x18-x27 which Java uses as temporary registers and C + // expects to be callee-save + // + // so the stub frame looks like this when we enter Java code + // + // [ return_from_Java ] <--- sp + // [ argument word n ] + // ... + // -22 [ argument word 1 ] + // -21 [ saved x27 ] <--- sp_after_call + // -20 [ saved x26 ] + // -19 [ saved x25 ] + // -18 [ saved x24 ] + // -17 [ saved x23 ] + // -16 [ saved x22 ] + // -15 [ saved x21 ] + // -14 [ saved x20 ] + // -13 [ saved x19 ] + // -12 [ saved x18 ] + // -11 [ saved x9 ] + // -10 [ call wrapper (x10) ] + // -9 [ result (x11) ] + // -8 [ result type (x12) ] + // -7 [ method (x13) ] + // -6 [ entry point (x14) ] + // -5 [ parameters (x15) ] + // -4 [ parameter size (x16) ] + // -3 [ thread (x17) ] + // -2 [ saved fp (x8) ] + // -1 [ saved ra (x1) ] + // 0 [ ] <--- fp == saved sp (x2) + + // Call stub stack layout word offsets from fp + enum call_stub_layout { + sp_after_call_off = -21, + + x27_off = -21, + x26_off = -20, + x25_off = -19, + x24_off = -18, + x23_off = -17, + x22_off = -16, + x21_off = -15, + x20_off = -14, + x19_off = -13, + x18_off = -12, + x9_off = -11, + + call_wrapper_off = -10, + result_off = -9, + result_type_off = -8, + method_off = -7, + entry_point_off = -6, + parameters_off = -5, + parameter_size_off = -4, + thread_off = -3, + fp_f = -2, + retaddr_off = -1, + }; + + address generate_call_stub(address& return_address) { + assert((int)frame::entry_frame_after_call_words == -(int)sp_after_call_off + 1 && + (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, + "adjust this code"); + + StubCodeMark mark(this, "StubRoutines", "call_stub"); + address start = __ pc(); + + const Address sp_after_call (fp, sp_after_call_off * wordSize); + + const Address call_wrapper (fp, call_wrapper_off * wordSize); + const Address result (fp, result_off * wordSize); + const Address result_type (fp, result_type_off * wordSize); + const Address method (fp, method_off * wordSize); + const Address entry_point (fp, entry_point_off * wordSize); + const Address parameters (fp, parameters_off * wordSize); + const Address parameter_size(fp, parameter_size_off * wordSize); + + const Address thread (fp, thread_off * wordSize); + + const Address x27_save (fp, x27_off * wordSize); + const Address x26_save (fp, x26_off * wordSize); + const Address x25_save (fp, x25_off * wordSize); + const Address x24_save (fp, x24_off * wordSize); + const Address x23_save (fp, x23_off * wordSize); + const Address x22_save (fp, x22_off * wordSize); + const Address x21_save (fp, x21_off * wordSize); + const Address x20_save (fp, x20_off * wordSize); + const Address x19_save (fp, x19_off * wordSize); + const Address x18_save (fp, x18_off * wordSize); + + const Address x9_save (fp, x9_off * wordSize); + + // stub code + + address riscv_entry = __ pc(); + + // set up frame and move sp to end of save area + __ enter(); + __ addi(sp, fp, sp_after_call_off * wordSize); + + // save register parameters and Java temporary/global registers + // n.b. we save thread even though it gets installed in + // xthread because we want to sanity check tp later + __ sd(c_rarg7, thread); + __ sw(c_rarg6, parameter_size); + __ sd(c_rarg5, parameters); + __ sd(c_rarg4, entry_point); + __ sd(c_rarg3, method); + __ sd(c_rarg2, result_type); + __ sd(c_rarg1, result); + __ sd(c_rarg0, call_wrapper); + + __ sd(x9, x9_save); + + __ sd(x18, x18_save); + __ sd(x19, x19_save); + __ sd(x20, x20_save); + __ sd(x21, x21_save); + __ sd(x22, x22_save); + __ sd(x23, x23_save); + __ sd(x24, x24_save); + __ sd(x25, x25_save); + __ sd(x26, x26_save); + __ sd(x27, x27_save); + + // install Java thread in global register now we have saved + // whatever value it held + __ mv(xthread, c_rarg7); + + // And method + __ mv(xmethod, c_rarg3); + + // set up the heapbase register + __ reinit_heapbase(); + +#ifdef ASSERT + // make sure we have no pending exceptions + { + Label L; + __ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); + __ beqz(t0, L); + __ stop("StubRoutines::call_stub: entered with pending exception"); + __ BIND(L); + } +#endif + // pass parameters if any + __ mv(esp, sp); + __ slli(t0, c_rarg6, LogBytesPerWord); + __ sub(t0, sp, t0); // Move SP out of the way + __ andi(sp, t0, -2 * wordSize); + + BLOCK_COMMENT("pass parameters if any"); + Label parameters_done; + // parameter count is still in c_rarg6 + // and parameter pointer identifying param 1 is in c_rarg5 + __ beqz(c_rarg6, parameters_done); + + address loop = __ pc(); + __ ld(t0, c_rarg5, 0); + __ addi(c_rarg5, c_rarg5, wordSize); + __ addi(c_rarg6, c_rarg6, -1); + __ push_reg(t0); + __ bgtz(c_rarg6, loop); + + __ BIND(parameters_done); + + // call Java entry -- passing methdoOop, and current sp + // xmethod: Method* + // x30: sender sp + BLOCK_COMMENT("call Java function"); + __ mv(x30, sp); + __ jalr(c_rarg4); + + // save current address for use by exception handling code + + return_address = __ pc(); + + // store result depending on type (everything that is not + // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) + // n.b. this assumes Java returns an integral result in x10 + // and a floating result in j_farg0 + __ ld(j_rarg2, result); + Label is_long, is_float, is_double, exit; + __ ld(j_rarg1, result_type); + __ li(t0, (u1)T_OBJECT); + __ beq(j_rarg1, t0, is_long); + __ li(t0, (u1)T_LONG); + __ beq(j_rarg1, t0, is_long); + __ li(t0, (u1)T_FLOAT); + __ beq(j_rarg1, t0, is_float); + __ li(t0, (u1)T_DOUBLE); + __ beq(j_rarg1, t0, is_double); + + // handle T_INT case + __ sw(x10, Address(j_rarg2)); + + __ BIND(exit); + + // pop parameters + __ addi(esp, fp, sp_after_call_off * wordSize); + +#ifdef ASSERT + // verify that threads correspond + { + Label L, S; + __ ld(t0, thread); + __ bne(xthread, t0, S); + __ get_thread(t0); + __ beq(xthread, t0, L); + __ BIND(S); + __ stop("StubRoutines::call_stub: threads must correspond"); + __ BIND(L); + } +#endif + + // restore callee-save registers + __ ld(x27, x27_save); + __ ld(x26, x26_save); + __ ld(x25, x25_save); + __ ld(x24, x24_save); + __ ld(x23, x23_save); + __ ld(x22, x22_save); + __ ld(x21, x21_save); + __ ld(x20, x20_save); + __ ld(x19, x19_save); + __ ld(x18, x18_save); + + __ ld(x9, x9_save); + + __ ld(c_rarg0, call_wrapper); + __ ld(c_rarg1, result); + __ ld(c_rarg2, result_type); + __ ld(c_rarg3, method); + __ ld(c_rarg4, entry_point); + __ ld(c_rarg5, parameters); + __ ld(c_rarg6, parameter_size); + __ ld(c_rarg7, thread); + + // leave frame and return to caller + __ leave(); + __ ret(); + + // handle return types different from T_INT + + __ BIND(is_long); + __ sd(x10, Address(j_rarg2, 0)); + __ j(exit); + + __ BIND(is_float); + __ fsw(j_farg0, Address(j_rarg2, 0), t0); + __ j(exit); + + __ BIND(is_double); + __ fsd(j_farg0, Address(j_rarg2, 0), t0); + __ j(exit); + + return start; + } + + // Return point for a Java call if there's an exception thrown in + // Java code. The exception is caught and transformed into a + // pending exception stored in JavaThread that can be tested from + // within the VM. + // + // Note: Usually the parameters are removed by the callee. In case + // of an exception crossing an activation frame boundary, that is + // not the case if the callee is compiled code => need to setup the + // sp. + // + // x10: exception oop + + address generate_catch_exception() { + StubCodeMark mark(this, "StubRoutines", "catch_exception"); + address start = __ pc(); + + // same as in generate_call_stub(): + const Address thread(fp, thread_off * wordSize); + +#ifdef ASSERT + // verify that threads correspond + { + Label L, S; + __ ld(t0, thread); + __ bne(xthread, t0, S); + __ get_thread(t0); + __ beq(xthread, t0, L); + __ bind(S); + __ stop("StubRoutines::catch_exception: threads must correspond"); + __ bind(L); + } +#endif + + // set pending exception + __ verify_oop(x10); + + __ sd(x10, Address(xthread, Thread::pending_exception_offset())); + __ mv(t0, (address)__FILE__); + __ sd(t0, Address(xthread, Thread::exception_file_offset())); + __ mv(t0, (int)__LINE__); + __ sw(t0, Address(xthread, Thread::exception_line_offset())); + + // complete return to VM + assert(StubRoutines::_call_stub_return_address != NULL, + "_call_stub_return_address must have been generated before"); + __ j(StubRoutines::_call_stub_return_address); + + return start; + } + + // Continuation point for runtime calls returning with a pending + // exception. The pending exception check happened in the runtime + // or native call stub. The pending exception in Thread is + // converted into a Java-level exception. + // + // Contract with Java-level exception handlers: + // x10: exception + // x13: throwing pc + // + // NOTE: At entry of this stub, exception-pc must be in RA !! + + // NOTE: this is always used as a jump target within generated code + // so it just needs to be generated code with no x86 prolog + + address generate_forward_exception() { + StubCodeMark mark(this, "StubRoutines", "forward exception"); + address start = __ pc(); + + // Upon entry, RA points to the return address returning into + // Java (interpreted or compiled) code; i.e., the return address + // becomes the throwing pc. + // + // Arguments pushed before the runtime call are still on the stack + // but the exception handler will reset the stack pointer -> + // ignore them. A potential result in registers can be ignored as + // well. + +#ifdef ASSERT + // make sure this code is only executed if there is a pending exception + { + Label L; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ bnez(t0, L); + __ stop("StubRoutines::forward exception: no pending exception (1)"); + __ bind(L); + } +#endif + + // compute exception handler into x9 + + // call the VM to find the handler address associated with the + // caller address. pass thread in x10 and caller pc (ret address) + // in x11. n.b. the caller pc is in ra, unlike x86 where it is on + // the stack. + __ mv(c_rarg1, ra); + // ra will be trashed by the VM call so we move it to x9 + // (callee-saved) because we also need to pass it to the handler + // returned by this call. + __ mv(x9, ra); + BLOCK_COMMENT("call exception_handler_for_return_address"); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, + SharedRuntime::exception_handler_for_return_address), + xthread, c_rarg1); + // we should not really care that ra is no longer the callee + // address. we saved the value the handler needs in x9 so we can + // just copy it to x13. however, the C2 handler will push its own + // frame and then calls into the VM and the VM code asserts that + // the PC for the frame above the handler belongs to a compiled + // Java method. So, we restore ra here to satisfy that assert. + __ mv(ra, x9); + // setup x10 & x13 & clear pending exception + __ mv(x13, x9); + __ mv(x9, x10); + __ ld(x10, Address(xthread, Thread::pending_exception_offset())); + __ sd(zr, Address(xthread, Thread::pending_exception_offset())); + +#ifdef ASSERT + // make sure exception is set + { + Label L; + __ bnez(x10, L); + __ stop("StubRoutines::forward exception: no pending exception (2)"); + __ bind(L); + } +#endif + + // continue at exception handler + // x10: exception + // x13: throwing pc + // x9: exception handler + __ verify_oop(x10); + __ jr(x9); + + return start; + } + + // Non-destructive plausibility checks for oops + // + // Arguments: + // x10: oop to verify + // t0: error message + // + // Stack after saving c_rarg3: + // [tos + 0]: saved c_rarg3 + // [tos + 1]: saved c_rarg2 + // [tos + 2]: saved ra + // [tos + 3]: saved t1 + // [tos + 4]: saved x10 + // [tos + 5]: saved t0 + address generate_verify_oop() { + + StubCodeMark mark(this, "StubRoutines", "verify_oop"); + address start = __ pc(); + + Label exit, error; + + __ push_reg(0x3000, sp); // save c_rarg2 and c_rarg3 + + __ la(c_rarg2, ExternalAddress((address) StubRoutines::verify_oop_count_addr())); + __ ld(c_rarg3, Address(c_rarg2)); + __ add(c_rarg3, c_rarg3, 1); + __ sd(c_rarg3, Address(c_rarg2)); + + // object is in x10 + // make sure object is 'reasonable' + __ beqz(x10, exit); // if obj is NULL it is OK + +#if INCLUDE_ZGC + if (UseZGC) { + // Check if mask is good. + // verifies that ZAddressBadMask & x10 == 0 + __ ld(c_rarg3, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); + __ andr(c_rarg2, x10, c_rarg3); + __ bnez(c_rarg2, error); + } +#endif + + // Check if the oop is in the right area of memory + __ mv(c_rarg3, (intptr_t) Universe::verify_oop_mask()); + __ andr(c_rarg2, x10, c_rarg3); + __ mv(c_rarg3, (intptr_t) Universe::verify_oop_bits()); + + // Compare c_rarg2 and c_rarg3. + __ bne(c_rarg2, c_rarg3, error); + + // make sure klass is 'reasonable', which is not zero. + __ load_klass(x10, x10); // get klass + __ beqz(x10, error); // if klass is NULL it is broken + + // return if everything seems ok + __ bind(exit); + + __ pop_reg(0x3000, sp); // pop c_rarg2 and c_rarg3 + __ ret(); + + // handle errors + __ bind(error); + __ pop_reg(0x3000, sp); // pop c_rarg2 and c_rarg3 + + __ pusha(); + // debug(char* msg, int64_t pc, int64_t regs[]) + __ mv(c_rarg0, t0); // pass address of error message + __ mv(c_rarg1, ra); // pass return address + __ mv(c_rarg2, sp); // pass address of regs on stack +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + BLOCK_COMMENT("call MacroAssembler::debug"); + int32_t offset = 0; + __ movptr_with_offset(t0, CAST_FROM_FN_PTR(address, MacroAssembler::debug64), offset); + __ jalr(x1, t0, offset); + __ ebreak(); + + return start; + } + + // The inner part of zero_words(). + // + // Inputs: + // x28: the HeapWord-aligned base address of an array to zero. + // x29: the count in HeapWords, x29 > 0. + // + // Returns x28 and x29, adjusted for the caller to clear. + // x28: the base address of the tail of words left to clear. + // x29: the number of words in the tail. + // x29 < MacroAssembler::zero_words_block_size. + + address generate_zero_blocks() { + Label done; + + const Register base = x28, cnt = x29; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "zero_blocks"); + address start = __ pc(); + + { + // Clear the remaining blocks. + Label loop; + __ sub(cnt, cnt, MacroAssembler::zero_words_block_size); + __ bltz(cnt, done); + __ bind(loop); + for (int i = 0; i < MacroAssembler::zero_words_block_size; i++) { + __ sd(zr, Address(base, 0)); + __ add(base, base, 8); + } + __ sub(cnt, cnt, MacroAssembler::zero_words_block_size); + __ bgez(cnt, loop); + __ bind(done); + __ add(cnt, cnt, MacroAssembler::zero_words_block_size); + } + + __ ret(); + + return start; + } + + typedef enum { + copy_forwards = 1, + copy_backwards = -1 + } copy_direction; + + // Bulk copy of blocks of 8 words. + // + // count is a count of words. + // + // Precondition: count >= 8 + // + // Postconditions: + // + // The least significant bit of count contains the remaining count + // of words to copy. The rest of count is trash. + // + // s and d are adjusted to point to the remaining words to copy + // + void generate_copy_longs(Label &start, Register s, Register d, Register count, + copy_direction direction) { + int unit = wordSize * direction; + int bias = wordSize; + + const Register tmp_reg0 = x13, tmp_reg1 = x14, tmp_reg2 = x15, tmp_reg3 = x16, + tmp_reg4 = x17, tmp_reg5 = x7, tmp_reg6 = x28, tmp_reg7 = x29; + + const Register stride = x30; + + assert_different_registers(t0, tmp_reg0, tmp_reg1, tmp_reg2, tmp_reg3, + tmp_reg4, tmp_reg5, tmp_reg6, tmp_reg7); + assert_different_registers(s, d, count, t0); + + Label again, drain; + const char* stub_name = NULL; + if (direction == copy_forwards) { + stub_name = "forward_copy_longs"; + } else { + stub_name = "backward_copy_longs"; + } + StubCodeMark mark(this, "StubRoutines", stub_name); + __ align(CodeEntryAlignment); + __ bind(start); + + if (direction == copy_forwards) { + __ sub(s, s, bias); + __ sub(d, d, bias); + } + +#ifdef ASSERT + // Make sure we are never given < 8 words + { + Label L; + + __ li(t0, 8); + __ bge(count, t0, L); + __ stop("genrate_copy_longs called with < 8 words"); + __ bind(L); + } +#endif + + __ ld(tmp_reg0, Address(s, 1 * unit)); + __ ld(tmp_reg1, Address(s, 2 * unit)); + __ ld(tmp_reg2, Address(s, 3 * unit)); + __ ld(tmp_reg3, Address(s, 4 * unit)); + __ ld(tmp_reg4, Address(s, 5 * unit)); + __ ld(tmp_reg5, Address(s, 6 * unit)); + __ ld(tmp_reg6, Address(s, 7 * unit)); + __ ld(tmp_reg7, Address(s, 8 * unit)); + __ addi(s, s, 8 * unit); + + __ sub(count, count, 16); + __ bltz(count, drain); + + __ bind(again); + + __ sd(tmp_reg0, Address(d, 1 * unit)); + __ sd(tmp_reg1, Address(d, 2 * unit)); + __ sd(tmp_reg2, Address(d, 3 * unit)); + __ sd(tmp_reg3, Address(d, 4 * unit)); + __ sd(tmp_reg4, Address(d, 5 * unit)); + __ sd(tmp_reg5, Address(d, 6 * unit)); + __ sd(tmp_reg6, Address(d, 7 * unit)); + __ sd(tmp_reg7, Address(d, 8 * unit)); + + __ ld(tmp_reg0, Address(s, 1 * unit)); + __ ld(tmp_reg1, Address(s, 2 * unit)); + __ ld(tmp_reg2, Address(s, 3 * unit)); + __ ld(tmp_reg3, Address(s, 4 * unit)); + __ ld(tmp_reg4, Address(s, 5 * unit)); + __ ld(tmp_reg5, Address(s, 6 * unit)); + __ ld(tmp_reg6, Address(s, 7 * unit)); + __ ld(tmp_reg7, Address(s, 8 * unit)); + + __ addi(s, s, 8 * unit); + __ addi(d, d, 8 * unit); + + __ sub(count, count, 8); + __ bgez(count, again); + + // Drain + __ bind(drain); + + __ sd(tmp_reg0, Address(d, 1 * unit)); + __ sd(tmp_reg1, Address(d, 2 * unit)); + __ sd(tmp_reg2, Address(d, 3 * unit)); + __ sd(tmp_reg3, Address(d, 4 * unit)); + __ sd(tmp_reg4, Address(d, 5 * unit)); + __ sd(tmp_reg5, Address(d, 6 * unit)); + __ sd(tmp_reg6, Address(d, 7 * unit)); + __ sd(tmp_reg7, Address(d, 8 * unit)); + __ addi(d, d, 8 * unit); + + { + Label L1, L2; + __ andi(t0, count, 4); + __ beqz(t0, L1); + + __ ld(tmp_reg0, Address(s, 1 * unit)); + __ ld(tmp_reg1, Address(s, 2 * unit)); + __ ld(tmp_reg2, Address(s, 3 * unit)); + __ ld(tmp_reg3, Address(s, 4 * unit)); + __ addi(s, s, 4 * unit); + + __ sd(tmp_reg0, Address(d, 1 * unit)); + __ sd(tmp_reg1, Address(d, 2 * unit)); + __ sd(tmp_reg2, Address(d, 3 * unit)); + __ sd(tmp_reg3, Address(d, 4 * unit)); + __ addi(d, d, 4 * unit); + + __ bind(L1); + + if (direction == copy_forwards) { + __ addi(s, s, bias); + __ addi(d, d, bias); + } + + __ andi(t0, count, 2); + __ beqz(t0, L2); + if (direction == copy_backwards) { + __ addi(s, s, 2 * unit); + __ ld(tmp_reg0, Address(s)); + __ ld(tmp_reg1, Address(s, wordSize)); + __ addi(d, d, 2 * unit); + __ sd(tmp_reg0, Address(d)); + __ sd(tmp_reg1, Address(d, wordSize)); + } else { + __ ld(tmp_reg0, Address(s)); + __ ld(tmp_reg1, Address(s, wordSize)); + __ addi(s, s, 2 * unit); + __ sd(tmp_reg0, Address(d)); + __ sd(tmp_reg1, Address(d, wordSize)); + __ addi(d, d, 2 * unit); + } + __ bind(L2); + } + + __ ret(); + } + + Label copy_f, copy_b; + + // All-singing all-dancing memory copy. + // + // Copy count units of memory from s to d. The size of a unit is + // step, which can be positive or negative depending on the direction + // of copy. If is_aligned is false, we align the source address. + // + /* + * if (is_aligned) { + * goto copy_8_bytes; + * } + * bool is_backwards = step < 0; + * int granularity = uabs(step); + * count = count * granularity; * count bytes + * + * if (is_backwards) { + * s += count; + * d += count; + * } + * + * count limit maybe greater than 16, for better performance + * if (count < 16) { + * goto copy_small; + * } + * + * if ((dst % 8) == (src % 8)) { + * aligned; + * goto copy8; + * } + * + * copy_small: + * load element one by one; + * done; + */ + + typedef void (MacroAssembler::*copy_insn)(Register Rd, const Address &adr, Register temp); + + void copy_memory_v(Register s, Register d, Register count, Register tmp, int step) { + bool is_backward = step < 0; + int granularity = uabs(step); + + const Register src = x30, dst = x31, vl = x14, cnt = x15, tmp1 = x16, tmp2 = x17; + assert_different_registers(s, d, cnt, vl, tmp, tmp1, tmp2); + Assembler::SEW sew = Assembler::elembytes_to_sew(granularity); + Label loop_forward, loop_backward, done; + + __ mv(dst, d); + __ mv(src, s); + __ mv(cnt, count); + + __ bind(loop_forward); + __ vsetvli(vl, cnt, sew, Assembler::m8); + if (is_backward) { + __ bne(vl, cnt, loop_backward); + } + + __ vlex_v(v0, src, sew); + __ sub(cnt, cnt, vl); + __ slli(vl, vl, (int)sew); + __ add(src, src, vl); + + __ vsex_v(v0, dst, sew); + __ add(dst, dst, vl); + __ bnez(cnt, loop_forward); + + if (is_backward) { + __ j(done); + + __ bind(loop_backward); + __ sub(tmp, cnt, vl); + __ slli(tmp, tmp, sew); + __ add(tmp1, s, tmp); + __ vlex_v(v0, tmp1, sew); + __ add(tmp2, d, tmp); + __ vsex_v(v0, tmp2, sew); + __ sub(cnt, cnt, vl); + __ bnez(cnt, loop_forward); + __ bind(done); + } + } + + void copy_memory(bool is_aligned, Register s, Register d, + Register count, Register tmp, int step) { + if (UseRVV) { + return copy_memory_v(s, d, count, tmp, step); + } + + bool is_backwards = step < 0; + int granularity = uabs(step); + + const Register src = x30, dst = x31, cnt = x15, tmp3 = x16, tmp4 = x17; + + Label same_aligned; + Label copy8, copy_small, done; + + copy_insn ld_arr = NULL, st_arr = NULL; + switch (granularity) { + case 1 : + ld_arr = (copy_insn)&MacroAssembler::lbu; + st_arr = (copy_insn)&MacroAssembler::sb; + break; + case 2 : + ld_arr = (copy_insn)&MacroAssembler::lhu; + st_arr = (copy_insn)&MacroAssembler::sh; + break; + case 4 : + ld_arr = (copy_insn)&MacroAssembler::lwu; + st_arr = (copy_insn)&MacroAssembler::sw; + break; + case 8 : + ld_arr = (copy_insn)&MacroAssembler::ld; + st_arr = (copy_insn)&MacroAssembler::sd; + break; + default : + ShouldNotReachHere(); + } + + __ beqz(count, done); + __ slli(cnt, count, exact_log2(granularity)); + if (is_backwards) { + __ add(src, s, cnt); + __ add(dst, d, cnt); + } else { + __ mv(src, s); + __ mv(dst, d); + } + + if (is_aligned) { + __ addi(tmp, cnt, -8); + __ bgez(tmp, copy8); + __ j(copy_small); + } + + __ mv(tmp, 16); + __ blt(cnt, tmp, copy_small); + + __ xorr(tmp, src, dst); + __ andi(tmp, tmp, 0b111); + __ bnez(tmp, copy_small); + + __ bind(same_aligned); + __ andi(tmp, src, 0b111); + __ beqz(tmp, copy8); + if (is_backwards) { + __ addi(src, src, step); + __ addi(dst, dst, step); + } + (_masm->*ld_arr)(tmp3, Address(src), t0); + (_masm->*st_arr)(tmp3, Address(dst), t0); + if (!is_backwards) { + __ addi(src, src, step); + __ addi(dst, dst, step); + } + __ addi(cnt, cnt, -granularity); + __ beqz(cnt, done); + __ j(same_aligned); + + __ bind(copy8); + if (is_backwards) { + __ addi(src, src, -wordSize); + __ addi(dst, dst, -wordSize); + } + __ ld(tmp3, Address(src)); + __ sd(tmp3, Address(dst)); + if (!is_backwards) { + __ addi(src, src, wordSize); + __ addi(dst, dst, wordSize); + } + __ addi(cnt, cnt, -wordSize); + __ addi(tmp4, cnt, -8); + __ bgez(tmp4, copy8); // cnt >= 8, do next loop + + __ beqz(cnt, done); + + __ bind(copy_small); + if (is_backwards) { + __ addi(src, src, step); + __ addi(dst, dst, step); + } + (_masm->*ld_arr)(tmp3, Address(src), t0); + (_masm->*st_arr)(tmp3, Address(dst), t0); + if (!is_backwards) { + __ addi(src, src, step); + __ addi(dst, dst, step); + } + __ addi(cnt, cnt, -granularity); + __ bgtz(cnt, copy_small); + + __ bind(done); + } + + // Scan over array at a for count oops, verifying each one. + // Preserves a and count, clobbers t0 and t1. + void verify_oop_array(size_t size, Register a, Register count, Register temp) { + Label loop, end; + __ mv(t1, zr); + __ slli(t0, count, exact_log2(size)); + __ bind(loop); + __ bgeu(t1, t0, end); + + __ add(temp, a, t1); + if (size == (size_t)wordSize) { + __ ld(temp, Address(temp, 0)); + __ verify_oop(temp); + } else { + __ lwu(temp, Address(temp, 0)); + __ decode_heap_oop(temp); // calls verify_oop + } + __ add(t1, t1, size); + __ j(loop); + __ bind(end); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // is_oop - true => oop array, so generate store check code + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let + // the hardware handle it. The two dwords within qwords that span + // cache line boundaries will still be loaded and stored atomicly. + // + // Side Effects: + // disjoint_int_copy_entry is set to the no-overlap entry point + // used by generate_conjoint_int_oop_copy(). + // + address generate_disjoint_copy(size_t size, bool aligned, bool is_oop, address* entry, + const char* name, bool dest_uninitialized = false) { + const Register s = c_rarg0, d = c_rarg1, count = c_rarg2; + RegSet saved_reg = RegSet::of(s, d, count); + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + __ enter(); + + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } + + DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT; + if (dest_uninitialized) { + decorators |= IS_DEST_UNINITIALIZED; + } + if (aligned) { + decorators |= ARRAYCOPY_ALIGNED; + } + + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->arraycopy_prologue(_masm, decorators, is_oop, s, d, count, saved_reg); + + if (is_oop) { + // save regs before copy_memory + __ push_reg(RegSet::of(d, count), sp); + } + + { + // UnsafeCopyMemory page error: continue after ucm + bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); + UnsafeCopyMemoryMark ucmm(this, add_entry, true); + copy_memory(aligned, s, d, count, t0, size); + } + + if (is_oop) { + __ pop_reg(RegSet::of(d, count), sp); + if (VerifyOops) { + verify_oop_array(size, d, count, t2); + } + } + + bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, t0, RegSet()); + + __ leave(); + __ mv(x10, zr); // return 0 + __ ret(); + return start; + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // is_oop - true => oop array, so generate store check code + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let + // the hardware handle it. The two dwords within qwords that span + // cache line boundaries will still be loaded and stored atomicly. + // + address generate_conjoint_copy(size_t size, bool aligned, bool is_oop, address nooverlap_target, + address* entry, const char* name, + bool dest_uninitialized = false) { + const Register s = c_rarg0, d = c_rarg1, count = c_rarg2; + RegSet saved_regs = RegSet::of(s, d, count); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + __ enter(); + + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } + + // use fwd copy when (d-s) above_equal (count*size) + __ sub(t0, d, s); + __ slli(t1, count, exact_log2(size)); + __ bgeu(t0, t1, nooverlap_target); + + DecoratorSet decorators = IN_HEAP | IS_ARRAY; + if (dest_uninitialized) { + decorators |= IS_DEST_UNINITIALIZED; + } + if (aligned) { + decorators |= ARRAYCOPY_ALIGNED; + } + + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->arraycopy_prologue(_masm, decorators, is_oop, s, d, count, saved_regs); + + if (is_oop) { + // save regs before copy_memory + __ push_reg(RegSet::of(d, count), sp); + } + + { + // UnsafeCopyMemory page error: continue after ucm + bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); + UnsafeCopyMemoryMark ucmm(this, add_entry, true); + copy_memory(aligned, s, d, count, t0, -size); + } + + if (is_oop) { + __ pop_reg(RegSet::of(d, count), sp); + if (VerifyOops) { + verify_oop_array(size, d, count, t2); + } + } + bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, t0, RegSet()); + __ leave(); + __ mv(x10, zr); // return 0 + __ ret(); + return start; + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, + // we let the hardware handle it. The one to eight bytes within words, + // dwords or qwords that span cache line boundaries will still be loaded + // and stored atomically. + // + // Side Effects: + // disjoint_byte_copy_entry is set to the no-overlap entry point // + // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, + // we let the hardware handle it. The one to eight bytes within words, + // dwords or qwords that span cache line boundaries will still be loaded + // and stored atomically. + // + // Side Effects: + // disjoint_byte_copy_entry is set to the no-overlap entry point + // used by generate_conjoint_byte_copy(). + // + address generate_disjoint_byte_copy(bool aligned, address* entry, const char* name) { + const bool not_oop = false; + return generate_disjoint_copy(sizeof (jbyte), aligned, not_oop, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, + // we let the hardware handle it. The one to eight bytes within words, + // dwords or qwords that span cache line boundaries will still be loaded + // and stored atomically. + // + address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, + address* entry, const char* name) { + const bool not_oop = false; + return generate_conjoint_copy(sizeof (jbyte), aligned, not_oop, nooverlap_target, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we + // let the hardware handle it. The two or four words within dwords + // or qwords that span cache line boundaries will still be loaded + // and stored atomically. + // + // Side Effects: + // disjoint_short_copy_entry is set to the no-overlap entry point + // used by generate_conjoint_short_copy(). + // + address generate_disjoint_short_copy(bool aligned, + address* entry, const char* name) { + const bool not_oop = false; + return generate_disjoint_copy(sizeof (jshort), aligned, not_oop, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we + // let the hardware handle it. The two or four words within dwords + // or qwords that span cache line boundaries will still be loaded + // and stored atomically. + // + address generate_conjoint_short_copy(bool aligned, address nooverlap_target, + address* entry, const char* name) { + const bool not_oop = false; + return generate_conjoint_copy(sizeof (jshort), aligned, not_oop, nooverlap_target, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let + // the hardware handle it. The two dwords within qwords that span + // cache line boundaries will still be loaded and stored atomicly. + // + // Side Effects: + // disjoint_int_copy_entry is set to the no-overlap entry point + // used by generate_conjoint_int_oop_copy(). + // + address generate_disjoint_int_copy(bool aligned, address* entry, + const char* name, bool dest_uninitialized = false) { + const bool not_oop = false; + return generate_disjoint_copy(sizeof (jint), aligned, not_oop, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // + // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let + // the hardware handle it. The two dwords within qwords that span + // cache line boundaries will still be loaded and stored atomicly. + // + address generate_conjoint_int_copy(bool aligned, address nooverlap_target, + address* entry, const char* name, + bool dest_uninitialized = false) { + const bool not_oop = false; + return generate_conjoint_copy(sizeof (jint), aligned, not_oop, nooverlap_target, entry, name); + } + + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as size_t, can be zero + // + // Side Effects: + // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the + // no-overlap entry point used by generate_conjoint_long_oop_copy(). + // + address generate_disjoint_long_copy(bool aligned, address* entry, + const char* name, bool dest_uninitialized = false) { + const bool not_oop = false; + return generate_disjoint_copy(sizeof (jlong), aligned, not_oop, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as size_t, can be zero + // + address generate_conjoint_long_copy(bool aligned, + address nooverlap_target, address* entry, + const char* name, bool dest_uninitialized = false) { + const bool not_oop = false; + return generate_conjoint_copy(sizeof (jlong), aligned, not_oop, nooverlap_target, entry, name); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as size_t, can be zero + // + // Side Effects: + // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the + // no-overlap entry point used by generate_conjoint_long_oop_copy(). + // + address generate_disjoint_oop_copy(bool aligned, address* entry, + const char* name, bool dest_uninitialized) { + const bool is_oop = true; + const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); + return generate_disjoint_copy(size, aligned, is_oop, entry, name, dest_uninitialized); + } + + // Arguments: + // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes + // ignored + // name - stub name string + // + // Inputs: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as size_t, can be zero + // + address generate_conjoint_oop_copy(bool aligned, + address nooverlap_target, address* entry, + const char* name, bool dest_uninitialized) { + const bool is_oop = true; + const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); + return generate_conjoint_copy(size, aligned, is_oop, nooverlap_target, entry, + name, dest_uninitialized); + } + + // Helper for generating a dynamic type check. + // Smashes t0, t1. + void generate_type_check(Register sub_klass, + Register super_check_offset, + Register super_klass, + Label& L_success) { + assert_different_registers(sub_klass, super_check_offset, super_klass); + + BLOCK_COMMENT("type_check:"); + + Label L_miss; + + __ check_klass_subtype_fast_path(sub_klass, super_klass, noreg, &L_success, &L_miss, NULL, super_check_offset); + __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, &L_success, NULL); + + // Fall through on failure! + __ BIND(L_miss); + } + + // + // Generate checkcasting array copy stub + // + // Input: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - element count, treated as ssize_t, can be zero + // c_rarg3 - size_t ckoff (super_check_offset) + // c_rarg4 - oop ckval (super_klass) + // + // Output: + // x10 == 0 - success + // x10 == -1^K - failure, where K is partial transfer count + // + address generate_checkcast_copy(const char* name, address* entry, + bool dest_uninitialized = false) { + Label L_load_element, L_store_element, L_do_card_marks, L_done, L_done_pop; + + // Input registers (after setup_arg_regs) + const Register from = c_rarg0; // source array address + const Register to = c_rarg1; // destination array address + const Register count = c_rarg2; // elementscount + const Register ckoff = c_rarg3; // super_check_offset + const Register ckval = c_rarg4; // super_klass + + RegSet wb_pre_saved_regs = RegSet::range(c_rarg0, c_rarg4); + RegSet wb_post_saved_regs = RegSet::of(count); + + // Registers used as temps (x7, x9, x18 are save-on-entry) + const Register count_save = x19; // orig elementscount + const Register start_to = x18; // destination array start address + const Register copied_oop = x7; // actual oop copied + const Register r9_klass = x9; // oop._klass + + //--------------------------------------------------------------- + // Assembler stub will be used for this call to arraycopy + // if the two arrays are subtypes of Object[] but the + // destination array type is not equal to or a supertype + // of the source type. Each element must be separately + // checked. + + assert_different_registers(from, to, count, ckoff, ckval, start_to, + copied_oop, r9_klass, count_save); + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + __ enter(); // required for proper stackwalking of RuntimeStub frame + + // Caller of this entry point must set up the argument registers. + if (entry != NULL) { + *entry = __ pc(); + BLOCK_COMMENT("Entry:"); + } + + // Empty array: Nothing to do + __ beqz(count, L_done); + + __ push_reg(RegSet::of(x7, x9, x18, x19), sp); + +#ifdef ASSERT + BLOCK_COMMENT("assert consistent ckoff/ckval"); + // The ckoff and ckval must be mutually consistent, + // even though caller generates both. + { Label L; + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + __ lwu(start_to, Address(ckval, sco_offset)); + __ beq(ckoff, start_to, L); + __ stop("super_check_offset inconsistent"); + __ bind(L); + } +#endif //ASSERT + + DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT; + bool is_oop = true; + if (dest_uninitialized) { + decorators |= IS_DEST_UNINITIALIZED; + } + + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->arraycopy_prologue(_masm, decorators, is_oop, from, to, count, wb_pre_saved_regs); + + // save the original count + __ mv(count_save, count); + + // Copy from low to high addresses + __ mv(start_to, to); // Save destination array start address + __ j(L_load_element); + + // ======== begin loop ======== + // (Loop is rotated; its entry is L_load_element.) + // Loop control: + // for count to 0 do + // copied_oop = load_heap_oop(from++) + // ... generate_type_check ... + // store_heap_oop(to++, copied_oop) + // end + + __ align(OptoLoopAlignment); + + __ BIND(L_store_element); + __ store_heap_oop(Address(to, 0), copied_oop, noreg, noreg, AS_RAW); // store the oop + __ add(to, to, UseCompressedOops ? 4 : 8); + __ sub(count, count, 1); + __ beqz(count, L_do_card_marks); + + // ======== loop entry is here ======== + __ BIND(L_load_element); + __ load_heap_oop(copied_oop, Address(from, 0), noreg, noreg, AS_RAW); // load the oop + __ add(from, from, UseCompressedOops ? 4 : 8); + __ beqz(copied_oop, L_store_element); + + __ load_klass(r9_klass, copied_oop);// query the object klass + generate_type_check(r9_klass, ckoff, ckval, L_store_element); + // ======== end loop ======== + + // It was a real error; we must depend on the caller to finish the job. + // Register count = remaining oops, count_orig = total oops. + // Emit GC store barriers for the oops we have copied and report + // their number to the caller. + + __ sub(count, count_save, count); // K = partially copied oop count + __ xori(count, count, -1); // report (-1^K) to caller + __ beqz(count, L_done_pop); + + __ BIND(L_do_card_marks); + bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, count_save, t0, wb_post_saved_regs); + + __ bind(L_done_pop); + __ pop_reg(RegSet::of(x7, x9, x18, x19), sp); + inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr); + + __ bind(L_done); + __ mv(x10, count); + __ leave(); + __ ret(); + + return start; + } + + // Perform range checks on the proposed arraycopy. + // Kills temp, but nothing else. + // Also, clean the sign bits of src_pos and dst_pos. + void arraycopy_range_checks(Register src, // source array oop (c_rarg0) + Register src_pos, // source position (c_rarg1) + Register dst, // destination array oo (c_rarg2) + Register dst_pos, // destination position (c_rarg3) + Register length, + Register temp, + Label& L_failed) { + BLOCK_COMMENT("arraycopy_range_checks:"); + + assert_different_registers(t0, temp); + + // if [src_pos + length > arrayOop(src)->length()] then FAIL + __ lwu(t0, Address(src, arrayOopDesc::length_offset_in_bytes())); + __ addw(temp, length, src_pos); + __ bgtu(temp, t0, L_failed); + + // if [dst_pos + length > arrayOop(dst)->length()] then FAIL + __ lwu(t0, Address(dst, arrayOopDesc::length_offset_in_bytes())); + __ addw(temp, length, dst_pos); + __ bgtu(temp, t0, L_failed); + + // Have to clean up high 32 bits of 'src_pos' and 'dst_pos'. + __ zero_extend(src_pos, src_pos, 32); + __ zero_extend(dst_pos, dst_pos, 32); + + BLOCK_COMMENT("arraycopy_range_checks done"); + } + + // + // Generate 'unsafe' array copy stub + // Though just as safe as the other stubs, it takes an unscaled + // size_t argument instead of an element count. + // + // Input: + // c_rarg0 - source array address + // c_rarg1 - destination array address + // c_rarg2 - byte count, treated as ssize_t, can be zero + // + // Examines the alignment of the operands and dispatches + // to a long, int, short, or byte copy loop. + // + address generate_unsafe_copy(const char* name, + address byte_copy_entry, + address short_copy_entry, + address int_copy_entry, + address long_copy_entry) { + assert_cond(byte_copy_entry != NULL && short_copy_entry != NULL && + int_copy_entry != NULL && long_copy_entry != NULL); + Label L_long_aligned, L_int_aligned, L_short_aligned; + const Register s = c_rarg0, d = c_rarg1, count = c_rarg2; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + // bump this on entry, not on exit: + inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr); + + __ orr(t0, s, d); + __ orr(t0, t0, count); + + __ andi(t0, t0, BytesPerLong - 1); + __ beqz(t0, L_long_aligned); + __ andi(t0, t0, BytesPerInt - 1); + __ beqz(t0, L_int_aligned); + __ andi(t0, t0, 1); + __ beqz(t0, L_short_aligned); + __ j(RuntimeAddress(byte_copy_entry)); + + __ BIND(L_short_aligned); + __ srli(count, count, LogBytesPerShort); // size => short_count + __ j(RuntimeAddress(short_copy_entry)); + __ BIND(L_int_aligned); + __ srli(count, count, LogBytesPerInt); // size => int_count + __ j(RuntimeAddress(int_copy_entry)); + __ BIND(L_long_aligned); + __ srli(count, count, LogBytesPerLong); // size => long_count + __ j(RuntimeAddress(long_copy_entry)); + + return start; + } + + // + // Generate generic array copy stubs + // + // Input: + // c_rarg0 - src oop + // c_rarg1 - src_pos (32-bits) + // c_rarg2 - dst oop + // c_rarg3 - dst_pos (32-bits) + // c_rarg4 - element count (32-bits) + // + // Output: + // x10 == 0 - success + // x10 == -1^K - failure, where K is partial transfer count + // + address generate_generic_copy(const char* name, + address byte_copy_entry, address short_copy_entry, + address int_copy_entry, address oop_copy_entry, + address long_copy_entry, address checkcast_copy_entry) { + assert_cond(byte_copy_entry != NULL && short_copy_entry != NULL && + int_copy_entry != NULL && oop_copy_entry != NULL && + long_copy_entry != NULL && checkcast_copy_entry != NULL); + Label L_failed, L_failed_0, L_objArray; + Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; + + // Input registers + const Register src = c_rarg0; // source array oop + const Register src_pos = c_rarg1; // source position + const Register dst = c_rarg2; // destination array oop + const Register dst_pos = c_rarg3; // destination position + const Register length = c_rarg4; + + // Registers used as temps + const Register dst_klass = c_rarg5; + + __ align(CodeEntryAlignment); + + StubCodeMark mark(this, "StubRoutines", name); + + address start = __ pc(); + + __ enter(); // required for proper stackwalking of RuntimeStub frame + + // bump this on entry, not on exit: + inc_counter_np(SharedRuntime::_generic_array_copy_ctr); + + //----------------------------------------------------------------------- + // Assembler stub will be used for this call to arraycopy + // if the following conditions are met: + // + // (1) src and dst must not be null. + // (2) src_pos must not be negative. + // (3) dst_pos must not be negative. + // (4) length must not be negative. + // (5) src klass and dst klass should be the same and not NULL. + // (6) src and dst should be arrays. + // (7) src_pos + length must not exceed length of src. + // (8) dst_pos + length must not exceed length of dst. + // + + // if [src == NULL] then return -1 + __ beqz(src, L_failed); + + // if [src_pos < 0] then return -1 + // i.e. sign bit set + __ andi(t0, src_pos, 1UL << 31); + __ bnez(t0, L_failed); + + // if [dst == NULL] then return -1 + __ beqz(dst, L_failed); + + // if [dst_pos < 0] then return -1 + // i.e. sign bit set + __ andi(t0, dst_pos, 1UL << 31); + __ bnez(t0, L_failed); + + // registers used as temp + const Register scratch_length = x28; // elements count to copy + const Register scratch_src_klass = x29; // array klass + const Register lh = x30; // layout helper + + // if [length < 0] then return -1 + __ addw(scratch_length, length, zr); // length (elements count, 32-bits value) + // i.e. sign bit set + __ andi(t0, scratch_length, 1UL << 31); + __ bnez(t0, L_failed); + + __ load_klass(scratch_src_klass, src); +#ifdef ASSERT + { + BLOCK_COMMENT("assert klasses not null {"); + Label L1, L2; + __ bnez(scratch_src_klass, L2); // it is broken if klass is NULL + __ bind(L1); + __ stop("broken null klass"); + __ bind(L2); + __ load_klass(t0, dst); + __ beqz(t0, L1); // this would be broken also + BLOCK_COMMENT("} assert klasses not null done"); + } +#endif + + // Load layout helper (32-bits) + // + // |array_tag| | header_size | element_type | |log2_element_size| + // 32 30 24 16 8 2 0 + // + // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 + // + + const int lh_offset = in_bytes(Klass::layout_helper_offset()); + + // Handle objArrays completely differently... + const jint objArray_lh = Klass::array_layout_helper(T_OBJECT); + __ lw(lh, Address(scratch_src_klass, lh_offset)); + __ mvw(t0, objArray_lh); + __ beq(lh, t0, L_objArray); + + // if [src->klass() != dst->klass()] then return -1 + __ load_klass(t1, dst); + __ bne(t1, scratch_src_klass, L_failed); + + // if [src->is_Array() != NULL] then return -1 + // i.e. (lh >= 0) + __ andi(t0, lh, 1UL << 31); + __ beqz(t0, L_failed); + + // At this point, it is known to be a typeArray (array_tag 0x3). +#ifdef ASSERT + { + BLOCK_COMMENT("assert primitive array {"); + Label L; + __ mvw(t1, Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift); + __ bge(lh, t1, L); + __ stop("must be a primitive array"); + __ bind(L); + BLOCK_COMMENT("} assert primitive array done"); + } +#endif + + arraycopy_range_checks(src, src_pos, dst, dst_pos, scratch_length, + t1, L_failed); + + // TypeArrayKlass + // + // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize) + // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize) + // + + const Register t0_offset = t0; // array offset + const Register x22_elsize = lh; // element size + + // Get array_header_in_bytes() + int lh_header_size_width = exact_log2(Klass::_lh_header_size_mask + 1); + int lh_header_size_msb = Klass::_lh_header_size_shift + lh_header_size_width; + __ slli(t0_offset, lh, XLEN - lh_header_size_msb); // left shift to remove 24 ~ 32; + __ srli(t0_offset, t0_offset, XLEN - lh_header_size_width); // array_offset + + __ add(src, src, t0_offset); // src array offset + __ add(dst, dst, t0_offset); // dst array offset + BLOCK_COMMENT("choose copy loop based on element size"); + + // next registers should be set before the jump to corresponding stub + const Register from = c_rarg0; // source array address + const Register to = c_rarg1; // destination array address + const Register count = c_rarg2; // elements count + + // 'from', 'to', 'count' registers should be set in such order + // since they are the same as 'src', 'src_pos', 'dst'. + + assert(Klass::_lh_log2_element_size_shift == 0, "fix this code"); + + // The possible values of elsize are 0-3, i.e. exact_log2(element + // size in bytes). We do a simple bitwise binary search. + __ BIND(L_copy_bytes); + __ andi(t0, x22_elsize, 2); + __ bnez(t0, L_copy_ints); + __ andi(t0, x22_elsize, 1); + __ bnez(t0, L_copy_shorts); + __ add(from, src, src_pos); // src_addr + __ add(to, dst, dst_pos); // dst_addr + __ addw(count, scratch_length, zr); // length + __ j(RuntimeAddress(byte_copy_entry)); + + __ BIND(L_copy_shorts); + __ shadd(from, src_pos, src, t0, 1); // src_addr + __ shadd(to, dst_pos, dst, t0, 1); // dst_addr + __ addw(count, scratch_length, zr); // length + __ j(RuntimeAddress(short_copy_entry)); + + __ BIND(L_copy_ints); + __ andi(t0, x22_elsize, 1); + __ bnez(t0, L_copy_longs); + __ shadd(from, src_pos, src, t0, 2); // src_addr + __ shadd(to, dst_pos, dst, t0, 2); // dst_addr + __ addw(count, scratch_length, zr); // length + __ j(RuntimeAddress(int_copy_entry)); + + __ BIND(L_copy_longs); +#ifdef ASSERT + { + BLOCK_COMMENT("assert long copy {"); + Label L; + __ andi(lh, lh, Klass::_lh_log2_element_size_mask); // lh -> x22_elsize + __ addw(lh, lh, zr); + __ mvw(t0, LogBytesPerLong); + __ beq(x22_elsize, t0, L); + __ stop("must be long copy, but elsize is wrong"); + __ bind(L); + BLOCK_COMMENT("} assert long copy done"); + } +#endif + __ shadd(from, src_pos, src, t0, 3); // src_addr + __ shadd(to, dst_pos, dst, t0, 3); // dst_addr + __ addw(count, scratch_length, zr); // length + __ j(RuntimeAddress(long_copy_entry)); + + // ObjArrayKlass + __ BIND(L_objArray); + // live at this point: scratch_src_klass, scratch_length, src[_pos], dst[_pos] + + Label L_plain_copy, L_checkcast_copy; + // test array classes for subtyping + __ load_klass(t2, dst); + __ bne(scratch_src_klass, t2, L_checkcast_copy); // usual case is exact equality + + // Identically typed arrays can be copied without element-wise checks. + arraycopy_range_checks(src, src_pos, dst, dst_pos, scratch_length, + t1, L_failed); + + __ shadd(from, src_pos, src, t0, LogBytesPerHeapOop); + __ add(from, from, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ shadd(to, dst_pos, dst, t0, LogBytesPerHeapOop); + __ add(to, to, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ addw(count, scratch_length, zr); // length + __ BIND(L_plain_copy); + __ j(RuntimeAddress(oop_copy_entry)); + + __ BIND(L_checkcast_copy); + // live at this point: scratch_src_klass, scratch_length, t2 (dst_klass) + { + // Before looking at dst.length, make sure dst is also an objArray. + __ lwu(t0, Address(t2, lh_offset)); + __ mvw(t1, objArray_lh); + __ bne(t0, t1, L_failed); + + // It is safe to examine both src.length and dst.length. + arraycopy_range_checks(src, src_pos, dst, dst_pos, scratch_length, + t2, L_failed); + + __ load_klass(dst_klass, dst); // reload + + // Marshal the base address arguments now, freeing registers. + __ shadd(from, src_pos, src, t0, LogBytesPerHeapOop); + __ add(from, from, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ shadd(to, dst_pos, dst, t0, LogBytesPerHeapOop); + __ add(to, to, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ addw(count, length, zr); // length (reloaded) + const Register sco_temp = c_rarg3; // this register is free now + assert_different_registers(from, to, count, sco_temp, + dst_klass, scratch_src_klass); + + // Generate the type check. + const int sco_offset = in_bytes(Klass::super_check_offset_offset()); + __ lwu(sco_temp, Address(dst_klass, sco_offset)); + + // Smashes t0, t1 + generate_type_check(scratch_src_klass, sco_temp, dst_klass, L_plain_copy); + + // Fetch destination element klass from the ObjArrayKlass header. + int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); + __ ld(dst_klass, Address(dst_klass, ek_offset)); + __ lwu(sco_temp, Address(dst_klass, sco_offset)); + + // the checkcast_copy loop needs two extra arguments: + assert(c_rarg3 == sco_temp, "#3 already in place"); + // Set up arguments for checkcast_copy_entry. + __ mv(c_rarg4, dst_klass); // dst.klass.element_klass + __ j(RuntimeAddress(checkcast_copy_entry)); + } + + __ BIND(L_failed); + __ li(x10, -1); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(); + + return start; + } + + // + // Generate stub for array fill. If "aligned" is true, the + // "to" address is assumed to be heapword aligned. + // + // Arguments for generated stub: + // to: c_rarg0 + // value: c_rarg1 + // count: c_rarg2 treated as signed + // + address generate_fill(BasicType t, bool aligned, const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + BLOCK_COMMENT("Entry:"); + + const Register to = c_rarg0; // source array address + const Register value = c_rarg1; // value + const Register count = c_rarg2; // elements count + + const Register bz_base = x28; // base for block_zero routine + const Register cnt_words = x29; // temp register + const Register tmp_reg = t1; + + __ enter(); + + Label L_fill_elements, L_exit1; + + int shift = -1; + switch (t) { + case T_BYTE: + shift = 0; + + // Zero extend value + // 8 bit -> 16 bit + __ andi(value, value, 0xff); + __ mv(tmp_reg, value); + __ slli(tmp_reg, tmp_reg, 8); + __ orr(value, value, tmp_reg); + + // 16 bit -> 32 bit + __ mv(tmp_reg, value); + __ slli(tmp_reg, tmp_reg, 16); + __ orr(value, value, tmp_reg); + + __ mv(tmp_reg, 8 >> shift); // Short arrays (< 8 bytes) fill by element + __ bltu(count, tmp_reg, L_fill_elements); + break; + case T_SHORT: + shift = 1; + // Zero extend value + // 16 bit -> 32 bit + __ andi(value, value, 0xffff); + __ mv(tmp_reg, value); + __ slli(tmp_reg, tmp_reg, 16); + __ orr(value, value, tmp_reg); + + // Short arrays (< 8 bytes) fill by element + __ mv(tmp_reg, 8 >> shift); + __ bltu(count, tmp_reg, L_fill_elements); + break; + case T_INT: + shift = 2; + + // Short arrays (< 8 bytes) fill by element + __ mv(tmp_reg, 8 >> shift); + __ bltu(count, tmp_reg, L_fill_elements); + break; + default: ShouldNotReachHere(); + } + + // Align source address at 8 bytes address boundary. + Label L_skip_align1, L_skip_align2, L_skip_align4; + if (!aligned) { + switch (t) { + case T_BYTE: + // One byte misalignment happens only for byte arrays. + __ andi(t0, to, 1); + __ beqz(t0, L_skip_align1); + __ sb(value, Address(to, 0)); + __ addi(to, to, 1); + __ addiw(count, count, -1); + __ bind(L_skip_align1); + // Fallthrough + case T_SHORT: + // Two bytes misalignment happens only for byte and short (char) arrays. + __ andi(t0, to, 2); + __ beqz(t0, L_skip_align2); + __ sh(value, Address(to, 0)); + __ addi(to, to, 2); + __ addiw(count, count, -(2 >> shift)); + __ bind(L_skip_align2); + // Fallthrough + case T_INT: + // Align to 8 bytes, we know we are 4 byte aligned to start. + __ andi(t0, to, 4); + __ beqz(t0, L_skip_align4); + __ sw(value, Address(to, 0)); + __ addi(to, to, 4); + __ addiw(count, count, -(4 >> shift)); + __ bind(L_skip_align4); + break; + default: ShouldNotReachHere(); + } + } + + // + // Fill large chunks + // + __ srliw(cnt_words, count, 3 - shift); // number of words + + // 32 bit -> 64 bit + __ andi(value, value, 0xffffffff); + __ mv(tmp_reg, value); + __ slli(tmp_reg, tmp_reg, 32); + __ orr(value, value, tmp_reg); + + __ slli(tmp_reg, cnt_words, 3 - shift); + __ subw(count, count, tmp_reg); + { + __ fill_words(to, cnt_words, value); + } + + // Remaining count is less than 8 bytes. Fill it by a single store. + // Note that the total length is no less than 8 bytes. + if (t == T_BYTE || t == T_SHORT) { + __ beqz(count, L_exit1); + __ shadd(to, count, to, tmp_reg, shift); // points to the end + __ sd(value, Address(to, -8)); // overwrite some elements + __ bind(L_exit1); + __ leave(); + __ ret(); + } + + // Handle copies less than 8 bytes. + Label L_fill_2, L_fill_4, L_exit2; + __ bind(L_fill_elements); + switch (t) { + case T_BYTE: + __ andi(t0, count, 1); + __ beqz(t0, L_fill_2); + __ sb(value, Address(to, 0)); + __ addi(to, to, 1); + __ bind(L_fill_2); + __ andi(t0, count, 2); + __ beqz(t0, L_fill_4); + __ sh(value, Address(to, 0)); + __ addi(to, to, 2); + __ bind(L_fill_4); + __ andi(t0, count, 4); + __ beqz(t0, L_exit2); + __ sw(value, Address(to, 0)); + break; + case T_SHORT: + __ andi(t0, count, 1); + __ beqz(t0, L_fill_4); + __ sh(value, Address(to, 0)); + __ addi(to, to, 2); + __ bind(L_fill_4); + __ andi(t0, count, 2); + __ beqz(t0, L_exit2); + __ sw(value, Address(to, 0)); + break; + case T_INT: + __ beqz(count, L_exit2); + __ sw(value, Address(to, 0)); + break; + default: ShouldNotReachHere(); + } + __ bind(L_exit2); + __ leave(); + __ ret(); + return start; + } + + void generate_arraycopy_stubs() { + address entry = NULL; + address entry_jbyte_arraycopy = NULL; + address entry_jshort_arraycopy = NULL; + address entry_jint_arraycopy = NULL; + address entry_oop_arraycopy = NULL; + address entry_jlong_arraycopy = NULL; + address entry_checkcast_arraycopy = NULL; + + generate_copy_longs(copy_f, c_rarg0, c_rarg1, t1, copy_forwards); + generate_copy_longs(copy_b, c_rarg0, c_rarg1, t1, copy_backwards); + + StubRoutines::riscv::_zero_blocks = generate_zero_blocks(); + + //*** jbyte + // Always need aligned and unaligned versions + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, + "jbyte_disjoint_arraycopy"); + StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, + &entry_jbyte_arraycopy, + "jbyte_arraycopy"); + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry, + "arrayof_jbyte_disjoint_arraycopy"); + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, entry, NULL, + "arrayof_jbyte_arraycopy"); + + //*** jshort + // Always need aligned and unaligned versions + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, + "jshort_disjoint_arraycopy"); + StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, + &entry_jshort_arraycopy, + "jshort_arraycopy"); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry, + "arrayof_jshort_disjoint_arraycopy"); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, entry, NULL, + "arrayof_jshort_arraycopy"); + + //*** jint + // Aligned versions + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry, + "arrayof_jint_disjoint_arraycopy"); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy, + "arrayof_jint_arraycopy"); + // In 64 bit we need both aligned and unaligned versions of jint arraycopy. + // entry_jint_arraycopy always points to the unaligned version + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry, + "jint_disjoint_arraycopy"); + StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, + &entry_jint_arraycopy, + "jint_arraycopy"); + + //*** jlong + // It is always aligned + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, &entry, + "arrayof_jlong_disjoint_arraycopy"); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, entry, &entry_jlong_arraycopy, + "arrayof_jlong_arraycopy"); + StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy; + StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy; + + //*** oops + { + // With compressed oops we need unaligned versions; notice that + // we overwrite entry_oop_arraycopy. + bool aligned = !UseCompressedOops; + + StubRoutines::_arrayof_oop_disjoint_arraycopy + = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy", + /*dest_uninitialized*/false); + StubRoutines::_arrayof_oop_arraycopy + = generate_conjoint_oop_copy(aligned, entry, &entry_oop_arraycopy, "arrayof_oop_arraycopy", + /*dest_uninitialized*/false); + // Aligned versions without pre-barriers + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit + = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_arrayof_oop_arraycopy_uninit + = generate_conjoint_oop_copy(aligned, entry, NULL, "arrayof_oop_arraycopy_uninit", + /*dest_uninitialized*/true); + } + + StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; + StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy; + StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit; + StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit; + + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, + /*dest_uninitialized*/true); + + + StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_jlong_arraycopy); + + StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_oop_arraycopy, + entry_jlong_arraycopy, + entry_checkcast_arraycopy); + + StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); + StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); + StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); + StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); + StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); + StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); + } + + // Safefetch stubs. + void generate_safefetch(const char* name, int size, address* entry, + address* fault_pc, address* continuation_pc) { + // safefetch signatures: + // int SafeFetch32(int* adr, int errValue) + // intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue) + // + // arguments: + // c_rarg0 = adr + // c_rarg1 = errValue + // + // result: + // PPC_RET = *adr or errValue + assert_cond(entry != NULL && fault_pc != NULL && continuation_pc != NULL); + StubCodeMark mark(this, "StubRoutines", name); + + // Entry point, pc or function descriptor. + *entry = __ pc(); + + // Load *adr into c_rarg1, may fault. + *fault_pc = __ pc(); + switch (size) { + case 4: + // int32_t + __ lw(c_rarg1, Address(c_rarg0, 0)); + break; + case 8: + // int64_t + __ ld(c_rarg1, Address(c_rarg0, 0)); + break; + default: + ShouldNotReachHere(); + } + + // return errValue or *adr + *continuation_pc = __ pc(); + __ mv(x10, c_rarg1); + __ ret(); + } + + // code for comparing 16 bytes of strings with same encoding + void compare_string_16_bytes_same(Label &DIFF1, Label &DIFF2) { + const Register result = x10, str1 = x11, cnt1 = x12, str2 = x13, tmp1 = x28, tmp2 = x29, tmp4 = x7, tmp5 = x31; + __ ld(tmp5, Address(str1)); + __ addi(str1, str1, 8); + __ xorr(tmp4, tmp1, tmp2); + __ ld(cnt1, Address(str2)); + __ addi(str2, str2, 8); + __ bnez(tmp4, DIFF1); + __ ld(tmp1, Address(str1)); + __ addi(str1, str1, 8); + __ xorr(tmp4, tmp5, cnt1); + __ ld(tmp2, Address(str2)); + __ addi(str2, str2, 8); + __ bnez(tmp4, DIFF2); + } + + // code for comparing 8 characters of strings with Latin1 and Utf16 encoding + void compare_string_8_x_LU(Register tmpL, Register tmpU, Label &DIFF1, + Label &DIFF2) { + const Register strU = x12, curU = x7, strL = x29, tmp = x30; + __ ld(tmpL, Address(strL)); + __ addi(strL, strL, 8); + __ ld(tmpU, Address(strU)); + __ addi(strU, strU, 8); + __ inflate_lo32(tmp, tmpL); + __ mv(t0, tmp); + __ xorr(tmp, curU, t0); + __ bnez(tmp, DIFF2); + + __ ld(curU, Address(strU)); + __ addi(strU, strU, 8); + __ inflate_hi32(tmp, tmpL); + __ mv(t0, tmp); + __ xorr(tmp, tmpU, t0); + __ bnez(tmp, DIFF1); + } + + // x10 = result + // x11 = str1 + // x12 = cnt1 + // x13 = str2 + // x14 = cnt2 + // x28 = tmp1 + // x29 = tmp2 + // x30 = tmp3 + address generate_compare_long_string_different_encoding(bool isLU) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", isLU ? "compare_long_string_different_encoding LU" : "compare_long_string_different_encoding UL"); + address entry = __ pc(); + Label SMALL_LOOP, TAIL, TAIL_LOAD_16, LOAD_LAST, DIFF1, DIFF2, + DONE, CALCULATE_DIFFERENCE; + const Register result = x10, str1 = x11, cnt1 = x12, str2 = x13, cnt2 = x14, + tmp1 = x28, tmp2 = x29, tmp3 = x30, tmp4 = x7, tmp5 = x31; + RegSet spilled_regs = RegSet::of(tmp4, tmp5); + + // cnt2 == amount of characters left to compare + // Check already loaded first 4 symbols + __ inflate_lo32(tmp3, isLU ? tmp1 : tmp2); + __ mv(isLU ? tmp1 : tmp2, tmp3); + __ addi(str1, str1, isLU ? wordSize / 2 : wordSize); + __ addi(str2, str2, isLU ? wordSize : wordSize / 2); + __ sub(cnt2, cnt2, 8); // Already loaded 4 symbols. Last 4 is special case. + __ push_reg(spilled_regs, sp); + + if (isLU) { + __ add(str1, str1, cnt2); + __ shadd(str2, cnt2, str2, t0, 1); + } else { + __ shadd(str1, cnt2, str1, t0, 1); + __ add(str2, str2, cnt2); + } + __ xorr(tmp3, tmp1, tmp2); + __ mv(tmp5, tmp2); + __ bnez(tmp3, CALCULATE_DIFFERENCE); + + Register strU = isLU ? str2 : str1, + strL = isLU ? str1 : str2, + tmpU = isLU ? tmp5 : tmp1, // where to keep U for comparison + tmpL = isLU ? tmp1 : tmp5; // where to keep L for comparison + + __ sub(tmp2, strL, cnt2); // strL pointer to load from + __ slli(t0, cnt2, 1); + __ sub(cnt1, strU, t0); // strU pointer to load from + + __ ld(tmp4, Address(cnt1)); + __ addi(cnt1, cnt1, 8); + __ beqz(cnt2, LOAD_LAST); // no characters left except last load + __ sub(cnt2, cnt2, 16); + __ bltz(cnt2, TAIL); + __ bind(SMALL_LOOP); // smaller loop + __ sub(cnt2, cnt2, 16); + compare_string_8_x_LU(tmpL, tmpU, DIFF1, DIFF2); + compare_string_8_x_LU(tmpL, tmpU, DIFF1, DIFF2); + __ bgez(cnt2, SMALL_LOOP); + __ addi(t0, cnt2, 16); + __ beqz(t0, LOAD_LAST); + __ bind(TAIL); // 1..15 characters left until last load (last 4 characters) + // Address of 8 bytes before last 4 characters in UTF-16 string + __ shadd(cnt1, cnt2, cnt1, t0, 1); + // Address of 16 bytes before last 4 characters in Latin1 string + __ add(tmp2, tmp2, cnt2); + __ ld(tmp4, Address(cnt1, -8)); + // last 16 characters before last load + compare_string_8_x_LU(tmpL, tmpU, DIFF1, DIFF2); + compare_string_8_x_LU(tmpL, tmpU, DIFF1, DIFF2); + __ j(LOAD_LAST); + __ bind(DIFF2); + __ mv(tmpU, tmp4); + __ bind(DIFF1); + __ mv(tmpL, t0); + __ j(CALCULATE_DIFFERENCE); + __ bind(LOAD_LAST); + // Last 4 UTF-16 characters are already pre-loaded into tmp4 by compare_string_8_x_LU. + // No need to load it again + __ mv(tmpU, tmp4); + __ ld(tmpL, Address(strL)); + __ inflate_lo32(tmp3, tmpL); + __ mv(tmpL, tmp3); + __ xorr(tmp3, tmpU, tmpL); + __ beqz(tmp3, DONE); + + // Find the first different characters in the longwords and + // compute their difference. + __ bind(CALCULATE_DIFFERENCE); + __ ctzc_bit(tmp4, tmp3); + __ srl(tmp1, tmp1, tmp4); + __ srl(tmp5, tmp5, tmp4); + __ andi(tmp1, tmp1, 0xFFFF); + __ andi(tmp5, tmp5, 0xFFFF); + __ sub(result, tmp1, tmp5); + __ bind(DONE); + __ pop_reg(spilled_regs, sp); + __ ret(); + return entry; + } + + address generate_method_entry_barrier() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier"); + + Label deoptimize_label; + + address start = __ pc(); + + __ set_last_Java_frame(sp, fp, ra, t0); + + __ enter(); + __ add(t1, sp, wordSize); + + __ sub(sp, sp, 4 * wordSize); + + __ push_call_clobbered_registers(); + + __ mv(c_rarg0, t1); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier), 1); + + __ reset_last_Java_frame(true); + + __ mv(t0, x10); + + __ pop_call_clobbered_registers(); + + __ bnez(t0, deoptimize_label); + + __ leave(); + __ ret(); + + __ BIND(deoptimize_label); + + __ ld(t0, Address(sp, 0)); + __ ld(fp, Address(sp, wordSize)); + __ ld(ra, Address(sp, wordSize * 2)); + __ ld(t1, Address(sp, wordSize * 3)); + + __ mv(sp, t0); + __ jr(t1); + + return start; + } + + // x10 = result + // x11 = str1 + // x12 = cnt1 + // x13 = str2 + // x14 = cnt2 + // x28 = tmp1 + // x29 = tmp2 + // x30 = tmp3 + // x31 = tmp4 + address generate_compare_long_string_same_encoding(bool isLL) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", isLL ? + "compare_long_string_same_encoding LL" : "compare_long_string_same_encoding UU"); + address entry = __ pc(); + Label SMALL_LOOP, CHECK_LAST, DIFF2, TAIL, + LENGTH_DIFF, DIFF, LAST_CHECK_AND_LENGTH_DIFF; + const Register result = x10, str1 = x11, cnt1 = x12, str2 = x13, cnt2 = x14, + tmp1 = x28, tmp2 = x29, tmp3 = x30, tmp4 = x7, tmp5 = x31; + RegSet spilled_regs = RegSet::of(tmp4, tmp5); + + // cnt1/cnt2 contains amount of characters to compare. cnt1 can be re-used + // update cnt2 counter with already loaded 8 bytes + __ sub(cnt2, cnt2, wordSize / (isLL ? 1 : 2)); + // update pointers, because of previous read + __ add(str1, str1, wordSize); + __ add(str2, str2, wordSize); + // less than 16 bytes left? + __ sub(cnt2, cnt2, isLL ? 16 : 8); + __ push_reg(spilled_regs, sp); + __ bltz(cnt2, TAIL); + __ bind(SMALL_LOOP); + compare_string_16_bytes_same(DIFF, DIFF2); + __ sub(cnt2, cnt2, isLL ? 16 : 8); + __ bgez(cnt2, SMALL_LOOP); + __ bind(TAIL); + __ addi(cnt2, cnt2, isLL ? 16 : 8); + __ beqz(cnt2, LAST_CHECK_AND_LENGTH_DIFF); + __ sub(cnt2, cnt2, isLL ? 8 : 4); + __ blez(cnt2, CHECK_LAST); + __ xorr(tmp4, tmp1, tmp2); + __ bnez(tmp4, DIFF); + __ ld(tmp1, Address(str1)); + __ addi(str1, str1, 8); + __ ld(tmp2, Address(str2)); + __ addi(str2, str2, 8); + __ sub(cnt2, cnt2, isLL ? 8 : 4); + __ bind(CHECK_LAST); + if (!isLL) { + __ add(cnt2, cnt2, cnt2); // now in bytes + } + __ xorr(tmp4, tmp1, tmp2); + __ bnez(tmp4, DIFF); + __ add(str1, str1, cnt2); + __ ld(tmp5, Address(str1)); + __ add(str2, str2, cnt2); + __ ld(cnt1, Address(str2)); + __ xorr(tmp4, tmp5, cnt1); + __ beqz(tmp4, LENGTH_DIFF); + // Find the first different characters in the longwords and + // compute their difference. + __ bind(DIFF2); + __ ctzc_bit(tmp3, tmp4, isLL); // count zero from lsb to msb + __ srl(tmp5, tmp5, tmp3); + __ srl(cnt1, cnt1, tmp3); + if (isLL) { + __ andi(tmp5, tmp5, 0xFF); + __ andi(cnt1, cnt1, 0xFF); + } else { + __ andi(tmp5, tmp5, 0xFFFF); + __ andi(cnt1, cnt1, 0xFFFF); + } + __ sub(result, tmp5, cnt1); + __ j(LENGTH_DIFF); + __ bind(DIFF); + __ ctzc_bit(tmp3, tmp4, isLL); // count zero from lsb to msb + __ srl(tmp1, tmp1, tmp3); + __ srl(tmp2, tmp2, tmp3); + if (isLL) { + __ andi(tmp1, tmp1, 0xFF); + __ andi(tmp2, tmp2, 0xFF); + } else { + __ andi(tmp1, tmp1, 0xFFFF); + __ andi(tmp2, tmp2, 0xFFFF); + } + __ sub(result, tmp1, tmp2); + __ j(LENGTH_DIFF); + __ bind(LAST_CHECK_AND_LENGTH_DIFF); + __ xorr(tmp4, tmp1, tmp2); + __ bnez(tmp4, DIFF); + __ bind(LENGTH_DIFF); + __ pop_reg(spilled_regs, sp); + __ ret(); + return entry; + } + + void generate_compare_long_strings() { + StubRoutines::riscv::_compare_long_string_LL = generate_compare_long_string_same_encoding(true); + StubRoutines::riscv::_compare_long_string_UU = generate_compare_long_string_same_encoding(false); + StubRoutines::riscv::_compare_long_string_LU = generate_compare_long_string_different_encoding(true); + StubRoutines::riscv::_compare_long_string_UL = generate_compare_long_string_different_encoding(false); + } + + // x10 result + // x11 src + // x12 src count + // x13 pattern + // x14 pattern count + address generate_string_indexof_linear(bool needle_isL, bool haystack_isL) + { + const char* stubName = needle_isL + ? (haystack_isL ? "indexof_linear_ll" : "indexof_linear_ul") + : "indexof_linear_uu"; + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stubName); + address entry = __ pc(); + + int needle_chr_size = needle_isL ? 1 : 2; + int haystack_chr_size = haystack_isL ? 1 : 2; + int needle_chr_shift = needle_isL ? 0 : 1; + int haystack_chr_shift = haystack_isL ? 0 : 1; + bool isL = needle_isL && haystack_isL; + // parameters + Register result = x10, haystack = x11, haystack_len = x12, needle = x13, needle_len = x14; + // temporary registers + Register mask1 = x20, match_mask = x21, first = x22, trailing_zeros = x23, mask2 = x24, tmp = x25; + // redefinitions + Register ch1 = x28, ch2 = x29; + RegSet spilled_regs = RegSet::range(x20, x25) + RegSet::range(x28, x29); + + __ push_reg(spilled_regs, sp); + + Label L_LOOP, L_LOOP_PROCEED, L_SMALL, L_HAS_ZERO, + L_HAS_ZERO_LOOP, L_CMP_LOOP, L_CMP_LOOP_NOMATCH, L_SMALL_PROCEED, + L_SMALL_HAS_ZERO_LOOP, L_SMALL_CMP_LOOP_NOMATCH, L_SMALL_CMP_LOOP, + L_POST_LOOP, L_CMP_LOOP_LAST_CMP, L_HAS_ZERO_LOOP_NOMATCH, + L_SMALL_CMP_LOOP_LAST_CMP, L_SMALL_CMP_LOOP_LAST_CMP2, + L_CMP_LOOP_LAST_CMP2, DONE, NOMATCH; + + __ ld(ch1, Address(needle)); + __ ld(ch2, Address(haystack)); + // src.length - pattern.length + __ sub(haystack_len, haystack_len, needle_len); + + // first is needle[0] + __ andi(first, ch1, needle_isL ? 0xFF : 0xFFFF, first); + uint64_t mask0101 = UCONST64(0x0101010101010101); + uint64_t mask0001 = UCONST64(0x0001000100010001); + __ mv(mask1, haystack_isL ? mask0101 : mask0001); + __ mul(first, first, mask1); + uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); + uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); + __ mv(mask2, haystack_isL ? mask7f7f : mask7fff); + if (needle_isL != haystack_isL) { + __ mv(tmp, ch1); + } + __ sub(haystack_len, haystack_len, wordSize / haystack_chr_size - 1); + __ blez(haystack_len, L_SMALL); + + if (needle_isL != haystack_isL) { + __ inflate_lo32(ch1, tmp, match_mask, trailing_zeros); + } + // xorr, sub, orr, notr, andr + // compare and set match_mask[i] with 0x80/0x8000 (Latin1/UTF16) if ch2[i] == first[i] + // eg: + // first: aa aa aa aa aa aa aa aa + // ch2: aa aa li nx jd ka aa aa + // match_mask: 80 80 00 00 00 00 80 80 + __ compute_match_mask(ch2, first, match_mask, mask1, mask2); + + // search first char of needle, if success, goto L_HAS_ZERO; + __ bnez(match_mask, L_HAS_ZERO); + __ sub(haystack_len, haystack_len, wordSize / haystack_chr_size); + __ add(result, result, wordSize / haystack_chr_size); + __ add(haystack, haystack, wordSize); + __ bltz(haystack_len, L_POST_LOOP); + + __ bind(L_LOOP); + __ ld(ch2, Address(haystack)); + __ compute_match_mask(ch2, first, match_mask, mask1, mask2); + __ bnez(match_mask, L_HAS_ZERO); + + __ bind(L_LOOP_PROCEED); + __ sub(haystack_len, haystack_len, wordSize / haystack_chr_size); + __ add(haystack, haystack, wordSize); + __ add(result, result, wordSize / haystack_chr_size); + __ bgez(haystack_len, L_LOOP); + + __ bind(L_POST_LOOP); + __ mv(ch2, -wordSize / haystack_chr_size); + __ ble(haystack_len, ch2, NOMATCH); // no extra characters to check + __ ld(ch2, Address(haystack)); + __ slli(haystack_len, haystack_len, LogBitsPerByte + haystack_chr_shift); + __ neg(haystack_len, haystack_len); + __ xorr(ch2, first, ch2); + __ sub(match_mask, ch2, mask1); + __ orr(ch2, ch2, mask2); + __ mv(trailing_zeros, -1); // all bits set + __ j(L_SMALL_PROCEED); + + __ align(OptoLoopAlignment); + __ bind(L_SMALL); + __ slli(haystack_len, haystack_len, LogBitsPerByte + haystack_chr_shift); + __ neg(haystack_len, haystack_len); + if (needle_isL != haystack_isL) { + __ inflate_lo32(ch1, tmp, match_mask, trailing_zeros); + } + __ xorr(ch2, first, ch2); + __ sub(match_mask, ch2, mask1); + __ orr(ch2, ch2, mask2); + __ mv(trailing_zeros, -1); // all bits set + + __ bind(L_SMALL_PROCEED); + __ srl(trailing_zeros, trailing_zeros, haystack_len); // mask. zeroes on useless bits. + __ notr(ch2, ch2); + __ andr(match_mask, match_mask, ch2); + __ andr(match_mask, match_mask, trailing_zeros); // clear useless bits and check + __ beqz(match_mask, NOMATCH); + + __ bind(L_SMALL_HAS_ZERO_LOOP); + __ ctzc_bit(trailing_zeros, match_mask, haystack_isL, ch2, tmp); // count trailing zeros + __ addi(trailing_zeros, trailing_zeros, haystack_isL ? 7 : 15); + __ mv(ch2, wordSize / haystack_chr_size); + __ ble(needle_len, ch2, L_SMALL_CMP_LOOP_LAST_CMP2); + __ compute_index(haystack, trailing_zeros, match_mask, result, ch2, tmp, haystack_isL); + __ mv(trailing_zeros, wordSize / haystack_chr_size); + __ bne(ch1, ch2, L_SMALL_CMP_LOOP_NOMATCH); + + __ bind(L_SMALL_CMP_LOOP); + __ shadd(first, trailing_zeros, needle, first, needle_chr_shift); + __ shadd(ch2, trailing_zeros, haystack, ch2, haystack_chr_shift); + needle_isL ? __ lbu(first, Address(first)) : __ lhu(first, Address(first)); + haystack_isL ? __ lbu(ch2, Address(ch2)) : __ lhu(ch2, Address(ch2)); + __ add(trailing_zeros, trailing_zeros, 1); + __ bge(trailing_zeros, needle_len, L_SMALL_CMP_LOOP_LAST_CMP); + __ beq(first, ch2, L_SMALL_CMP_LOOP); + + __ bind(L_SMALL_CMP_LOOP_NOMATCH); + __ beqz(match_mask, NOMATCH); + __ ctzc_bit(trailing_zeros, match_mask, haystack_isL, tmp, ch2); + __ addi(trailing_zeros, trailing_zeros, haystack_isL ? 7 : 15); + __ add(result, result, 1); + __ add(haystack, haystack, haystack_chr_size); + __ j(L_SMALL_HAS_ZERO_LOOP); + + __ align(OptoLoopAlignment); + __ bind(L_SMALL_CMP_LOOP_LAST_CMP); + __ bne(first, ch2, L_SMALL_CMP_LOOP_NOMATCH); + __ j(DONE); + + __ align(OptoLoopAlignment); + __ bind(L_SMALL_CMP_LOOP_LAST_CMP2); + __ compute_index(haystack, trailing_zeros, match_mask, result, ch2, tmp, haystack_isL); + __ bne(ch1, ch2, L_SMALL_CMP_LOOP_NOMATCH); + __ j(DONE); + + __ align(OptoLoopAlignment); + __ bind(L_HAS_ZERO); + __ ctzc_bit(trailing_zeros, match_mask, haystack_isL, tmp, ch2); + __ addi(trailing_zeros, trailing_zeros, haystack_isL ? 7 : 15); + __ slli(needle_len, needle_len, BitsPerByte * wordSize / 2); + __ orr(haystack_len, haystack_len, needle_len); // restore needle_len(32bits) + __ sub(result, result, 1); // array index from 0, so result -= 1 + + __ bind(L_HAS_ZERO_LOOP); + __ mv(needle_len, wordSize / haystack_chr_size); + __ srli(ch2, haystack_len, BitsPerByte * wordSize / 2); + __ bge(needle_len, ch2, L_CMP_LOOP_LAST_CMP2); + // load next 8 bytes from haystack, and increase result index + __ compute_index(haystack, trailing_zeros, match_mask, result, ch2, tmp, haystack_isL); + __ add(result, result, 1); + __ mv(trailing_zeros, wordSize / haystack_chr_size); + __ bne(ch1, ch2, L_CMP_LOOP_NOMATCH); + + // compare one char + __ bind(L_CMP_LOOP); + __ shadd(needle_len, trailing_zeros, needle, needle_len, needle_chr_shift); + needle_isL ? __ lbu(needle_len, Address(needle_len)) : __ lhu(needle_len, Address(needle_len)); + __ shadd(ch2, trailing_zeros, haystack, ch2, haystack_chr_shift); + haystack_isL ? __ lbu(ch2, Address(ch2)) : __ lhu(ch2, Address(ch2)); + __ add(trailing_zeros, trailing_zeros, 1); // next char index + __ srli(tmp, haystack_len, BitsPerByte * wordSize / 2); + __ bge(trailing_zeros, tmp, L_CMP_LOOP_LAST_CMP); + __ beq(needle_len, ch2, L_CMP_LOOP); + + __ bind(L_CMP_LOOP_NOMATCH); + __ beqz(match_mask, L_HAS_ZERO_LOOP_NOMATCH); + __ ctzc_bit(trailing_zeros, match_mask, haystack_isL, needle_len, ch2); // find next "first" char index + __ addi(trailing_zeros, trailing_zeros, haystack_isL ? 7 : 15); + __ add(haystack, haystack, haystack_chr_size); + __ j(L_HAS_ZERO_LOOP); + + __ align(OptoLoopAlignment); + __ bind(L_CMP_LOOP_LAST_CMP); + __ bne(needle_len, ch2, L_CMP_LOOP_NOMATCH); + __ j(DONE); + + __ align(OptoLoopAlignment); + __ bind(L_CMP_LOOP_LAST_CMP2); + __ compute_index(haystack, trailing_zeros, match_mask, result, ch2, tmp, haystack_isL); + __ add(result, result, 1); + __ bne(ch1, ch2, L_CMP_LOOP_NOMATCH); + __ j(DONE); + + __ align(OptoLoopAlignment); + __ bind(L_HAS_ZERO_LOOP_NOMATCH); + // 1) Restore "result" index. Index was wordSize/str2_chr_size * N until + // L_HAS_ZERO block. Byte octet was analyzed in L_HAS_ZERO_LOOP, + // so, result was increased at max by wordSize/str2_chr_size - 1, so, + // respective high bit wasn't changed. L_LOOP_PROCEED will increase + // result by analyzed characters value, so, we can just reset lower bits + // in result here. Clear 2 lower bits for UU/UL and 3 bits for LL + // 2) restore needle_len and haystack_len values from "compressed" haystack_len + // 3) advance haystack value to represent next haystack octet. result & 7/3 is + // index of last analyzed substring inside current octet. So, haystack in at + // respective start address. We need to advance it to next octet + __ andi(match_mask, result, wordSize / haystack_chr_size - 1); + __ srli(needle_len, haystack_len, BitsPerByte * wordSize / 2); + __ andi(result, result, haystack_isL ? -8 : -4); + __ slli(tmp, match_mask, haystack_chr_shift); + __ sub(haystack, haystack, tmp); + __ addw(haystack_len, haystack_len, zr); + __ j(L_LOOP_PROCEED); + + __ align(OptoLoopAlignment); + __ bind(NOMATCH); + __ mv(result, -1); + + __ bind(DONE); + __ pop_reg(spilled_regs, sp); + __ ret(); + return entry; + } + + void generate_string_indexof_stubs() + { + StubRoutines::riscv::_string_indexof_linear_ll = generate_string_indexof_linear(true, true); + StubRoutines::riscv::_string_indexof_linear_uu = generate_string_indexof_linear(false, false); + StubRoutines::riscv::_string_indexof_linear_ul = generate_string_indexof_linear(true, false); + } + +#ifdef COMPILER2 + address generate_mulAdd() + { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "mulAdd"); + + address entry = __ pc(); + + const Register out = x10; + const Register in = x11; + const Register offset = x12; + const Register len = x13; + const Register k = x14; + const Register tmp = x28; + + BLOCK_COMMENT("Entry:"); + __ enter(); + __ mul_add(out, in, offset, len, k, tmp); + __ leave(); + __ ret(); + + return entry; + } + + /** + * Arguments: + * + * Input: + * c_rarg0 - x address + * c_rarg1 - x length + * c_rarg2 - y address + * c_rarg3 - y length + * c_rarg4 - z address + * c_rarg5 - z length + */ + address generate_multiplyToLen() + { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "multiplyToLen"); + address entry = __ pc(); + + const Register x = x10; + const Register xlen = x11; + const Register y = x12; + const Register ylen = x13; + const Register z = x14; + const Register zlen = x15; + + const Register tmp1 = x16; + const Register tmp2 = x17; + const Register tmp3 = x7; + const Register tmp4 = x28; + const Register tmp5 = x29; + const Register tmp6 = x30; + const Register tmp7 = x31; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + __ multiply_to_len(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(); + + return entry; + } + + address generate_squareToLen() + { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "squareToLen"); + address entry = __ pc(); + + const Register x = x10; + const Register xlen = x11; + const Register z = x12; + const Register zlen = x13; + const Register y = x14; // == x + const Register ylen = x15; // == xlen + + const Register tmp1 = x16; + const Register tmp2 = x17; + const Register tmp3 = x7; + const Register tmp4 = x28; + const Register tmp5 = x29; + const Register tmp6 = x30; + const Register tmp7 = x31; + + BLOCK_COMMENT("Entry:"); + __ enter(); + __ mv(y, x); + __ mv(ylen, xlen); + __ multiply_to_len(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7); + __ leave(); + __ ret(); + + return entry; + } + + // Arguments: + // + // Input: + // c_rarg0 - newArr address + // c_rarg1 - oldArr address + // c_rarg2 - newIdx + // c_rarg3 - shiftCount + // c_rarg4 - numIter + // + address generate_bigIntegerLeftShift() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "bigIntegerLeftShiftWorker"); + address entry = __ pc(); + + Label loop, exit; + + Register newArr = c_rarg0; + Register oldArr = c_rarg1; + Register newIdx = c_rarg2; + Register shiftCount = c_rarg3; + Register numIter = c_rarg4; + + Register shiftRevCount = c_rarg5; + Register oldArrNext = t1; + + __ beqz(numIter, exit); + __ shadd(newArr, newIdx, newArr, t0, 2); + + __ li(shiftRevCount, 32); + __ sub(shiftRevCount, shiftRevCount, shiftCount); + + __ bind(loop); + __ addi(oldArrNext, oldArr, 4); + __ vsetvli(t0, numIter, Assembler::e32, Assembler::m4); + __ vle32_v(v0, oldArr); + __ vle32_v(v4, oldArrNext); + __ vsll_vx(v0, v0, shiftCount); + __ vsrl_vx(v4, v4, shiftRevCount); + __ vor_vv(v0, v0, v4); + __ vse32_v(v0, newArr); + __ sub(numIter, numIter, t0); + __ shadd(oldArr, t0, oldArr, t1, 2); + __ shadd(newArr, t0, newArr, t1, 2); + __ bnez(numIter, loop); + + __ bind(exit); + __ ret(); + + return entry; + } + + // Arguments: + // + // Input: + // c_rarg0 - newArr address + // c_rarg1 - oldArr address + // c_rarg2 - newIdx + // c_rarg3 - shiftCount + // c_rarg4 - numIter + // + address generate_bigIntegerRightShift() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "bigIntegerRightShiftWorker"); + address entry = __ pc(); + + Label loop, exit; + + Register newArr = c_rarg0; + Register oldArr = c_rarg1; + Register newIdx = c_rarg2; + Register shiftCount = c_rarg3; + Register numIter = c_rarg4; + Register idx = numIter; + + Register shiftRevCount = c_rarg5; + Register oldArrNext = c_rarg6; + Register newArrCur = t0; + Register oldArrCur = t1; + + __ beqz(idx, exit); + __ shadd(newArr, newIdx, newArr, t0, 2); + + __ li(shiftRevCount, 32); + __ sub(shiftRevCount, shiftRevCount, shiftCount); + + __ bind(loop); + __ vsetvli(t0, idx, Assembler::e32, Assembler::m4); + __ sub(idx, idx, t0); + __ shadd(oldArrNext, idx, oldArr, t1, 2); + __ shadd(newArrCur, idx, newArr, t1, 2); + __ addi(oldArrCur, oldArrNext, 4); + __ vle32_v(v0, oldArrCur); + __ vle32_v(v4, oldArrNext); + __ vsrl_vx(v0, v0, shiftCount); + __ vsll_vx(v4, v4, shiftRevCount); + __ vor_vv(v0, v0, v4); + __ vse32_v(v0, newArrCur); + __ bnez(idx, loop); + + __ bind(exit); + __ ret(); + + return entry; + } +#endif + +#ifdef COMPILER2 + class MontgomeryMultiplyGenerator : public MacroAssembler { + + Register Pa_base, Pb_base, Pn_base, Pm_base, inv, Rlen, Ra, Rb, Rm, Rn, + Pa, Pb, Pn, Pm, Rhi_ab, Rlo_ab, Rhi_mn, Rlo_mn, tmp0, tmp1, tmp2, Ri, Rj; + + RegSet _toSave; + bool _squaring; + + public: + MontgomeryMultiplyGenerator (Assembler *as, bool squaring) + : MacroAssembler(as->code()), _squaring(squaring) { + + // Register allocation + + Register reg = c_rarg0; + Pa_base = reg; // Argument registers + if (squaring) { + Pb_base = Pa_base; + } else { + Pb_base = ++reg; + } + Pn_base = ++reg; + Rlen= ++reg; + inv = ++reg; + Pm_base = ++reg; + + // Working registers: + Ra = ++reg; // The current digit of a, b, n, and m. + Rb = ++reg; + Rm = ++reg; + Rn = ++reg; + + Pa = ++reg; // Pointers to the current/next digit of a, b, n, and m. + Pb = ++reg; + Pm = ++reg; + Pn = ++reg; + + tmp0 = ++reg; // Three registers which form a + tmp1 = ++reg; // triple-precision accumuator. + tmp2 = ++reg; + + Ri = x6; // Inner and outer loop indexes. + Rj = x7; + + Rhi_ab = x28; // Product registers: low and high parts + Rlo_ab = x29; // of a*b and m*n. + Rhi_mn = x30; + Rlo_mn = x31; + + // x18 and up are callee-saved. + _toSave = RegSet::range(x18, reg) + Pm_base; + } + + private: + void save_regs() { + push_reg(_toSave, sp); + } + + void restore_regs() { + pop_reg(_toSave, sp); + } + + template + void unroll_2(Register count, T block) { + Label loop, end, odd; + beqz(count, end); + andi(t0, count, 0x1); + bnez(t0, odd); + align(16); + bind(loop); + (this->*block)(); + bind(odd); + (this->*block)(); + addi(count, count, -2); + bgtz(count, loop); + bind(end); + } + + template + void unroll_2(Register count, T block, Register d, Register s, Register tmp) { + Label loop, end, odd; + beqz(count, end); + andi(tmp, count, 0x1); + bnez(tmp, odd); + align(16); + bind(loop); + (this->*block)(d, s, tmp); + bind(odd); + (this->*block)(d, s, tmp); + addi(count, count, -2); + bgtz(count, loop); + bind(end); + } + + void pre1(RegisterOrConstant i) { + block_comment("pre1"); + // Pa = Pa_base; + // Pb = Pb_base + i; + // Pm = Pm_base; + // Pn = Pn_base + i; + // Ra = *Pa; + // Rb = *Pb; + // Rm = *Pm; + // Rn = *Pn; + if (i.is_register()) { + slli(t0, i.as_register(), LogBytesPerWord); + } else { + mv(t0, i.as_constant()); + slli(t0, t0, LogBytesPerWord); + } + + mv(Pa, Pa_base); + add(Pb, Pb_base, t0); + mv(Pm, Pm_base); + add(Pn, Pn_base, t0); + + ld(Ra, Address(Pa)); + ld(Rb, Address(Pb)); + ld(Rm, Address(Pm)); + ld(Rn, Address(Pn)); + + // Zero the m*n result. + mv(Rhi_mn, zr); + mv(Rlo_mn, zr); + } + + // The core multiply-accumulate step of a Montgomery + // multiplication. The idea is to schedule operations as a + // pipeline so that instructions with long latencies (loads and + // multiplies) have time to complete before their results are + // used. This most benefits in-order implementations of the + // architecture but out-of-order ones also benefit. + void step() { + block_comment("step"); + // MACC(Ra, Rb, tmp0, tmp1, tmp2); + // Ra = *++Pa; + // Rb = *--Pb; + mulhu(Rhi_ab, Ra, Rb); + mul(Rlo_ab, Ra, Rb); + addi(Pa, Pa, wordSize); + ld(Ra, Address(Pa)); + addi(Pb, Pb, -wordSize); + ld(Rb, Address(Pb)); + acc(Rhi_mn, Rlo_mn, tmp0, tmp1, tmp2); // The pending m*n from the + // previous iteration. + // MACC(Rm, Rn, tmp0, tmp1, tmp2); + // Rm = *++Pm; + // Rn = *--Pn; + mulhu(Rhi_mn, Rm, Rn); + mul(Rlo_mn, Rm, Rn); + addi(Pm, Pm, wordSize); + ld(Rm, Address(Pm)); + addi(Pn, Pn, -wordSize); + ld(Rn, Address(Pn)); + acc(Rhi_ab, Rlo_ab, tmp0, tmp1, tmp2); + } + + void post1() { + block_comment("post1"); + + // MACC(Ra, Rb, tmp0, tmp1, tmp2); + // Ra = *++Pa; + // Rb = *--Pb; + mulhu(Rhi_ab, Ra, Rb); + mul(Rlo_ab, Ra, Rb); + acc(Rhi_mn, Rlo_mn, tmp0, tmp1, tmp2); // The pending m*n + acc(Rhi_ab, Rlo_ab, tmp0, tmp1, tmp2); + + // *Pm = Rm = tmp0 * inv; + mul(Rm, tmp0, inv); + sd(Rm, Address(Pm)); + + // MACC(Rm, Rn, tmp0, tmp1, tmp2); + // tmp0 = tmp1; tmp1 = tmp2; tmp2 = 0; + mulhu(Rhi_mn, Rm, Rn); + +#ifndef PRODUCT + // assert(m[i] * n[0] + tmp0 == 0, "broken Montgomery multiply"); + { + mul(Rlo_mn, Rm, Rn); + add(Rlo_mn, tmp0, Rlo_mn); + Label ok; + beqz(Rlo_mn, ok); + stop("broken Montgomery multiply"); + bind(ok); + } +#endif + // We have very carefully set things up so that + // m[i]*n[0] + tmp0 == 0 (mod b), so we don't have to calculate + // the lower half of Rm * Rn because we know the result already: + // it must be -tmp0. tmp0 + (-tmp0) must generate a carry iff + // tmp0 != 0. So, rather than do a mul and an cad we just set + // the carry flag iff tmp0 is nonzero. + // + // mul(Rlo_mn, Rm, Rn); + // cad(zr, tmp0, Rlo_mn); + addi(t0, tmp0, -1); + sltu(t0, t0, tmp0); // Set carry iff tmp0 is nonzero + cadc(tmp0, tmp1, Rhi_mn, t0); + adc(tmp1, tmp2, zr, t0); + mv(tmp2, zr); + } + + void pre2(Register i, Register len) { + block_comment("pre2"); + // Pa = Pa_base + i-len; + // Pb = Pb_base + len; + // Pm = Pm_base + i-len; + // Pn = Pn_base + len; + + sub(Rj, i, len); + // Rj == i-len + + // Ra as temp register + slli(Ra, Rj, LogBytesPerWord); + add(Pa, Pa_base, Ra); + add(Pm, Pm_base, Ra); + slli(Ra, len, LogBytesPerWord); + add(Pb, Pb_base, Ra); + add(Pn, Pn_base, Ra); + + // Ra = *++Pa; + // Rb = *--Pb; + // Rm = *++Pm; + // Rn = *--Pn; + add(Pa, Pa, wordSize); + ld(Ra, Address(Pa)); + add(Pb, Pb, -wordSize); + ld(Rb, Address(Pb)); + add(Pm, Pm, wordSize); + ld(Rm, Address(Pm)); + add(Pn, Pn, -wordSize); + ld(Rn, Address(Pn)); + + mv(Rhi_mn, zr); + mv(Rlo_mn, zr); + } + + void post2(Register i, Register len) { + block_comment("post2"); + sub(Rj, i, len); + + cad(tmp0, tmp0, Rlo_mn, t0); // The pending m*n, low part + + // As soon as we know the least significant digit of our result, + // store it. + // Pm_base[i-len] = tmp0; + // Rj as temp register + slli(Rj, Rj, LogBytesPerWord); + add(Rj, Pm_base, Rj); + sd(tmp0, Address(Rj)); + + // tmp0 = tmp1; tmp1 = tmp2; tmp2 = 0; + cadc(tmp0, tmp1, Rhi_mn, t0); // The pending m*n, high part + adc(tmp1, tmp2, zr, t0); + mv(tmp2, zr); + } + + // A carry in tmp0 after Montgomery multiplication means that we + // should subtract multiples of n from our result in m. We'll + // keep doing that until there is no carry. + void normalize(Register len) { + block_comment("normalize"); + // while (tmp0) + // tmp0 = sub(Pm_base, Pn_base, tmp0, len); + Label loop, post, again; + Register cnt = tmp1, i = tmp2; // Re-use registers; we're done with them now + beqz(tmp0, post); { + bind(again); { + mv(i, zr); + mv(cnt, len); + slli(Rn, i, LogBytesPerWord); + add(Rm, Pm_base, Rn); + ld(Rm, Address(Rm)); + add(Rn, Pn_base, Rn); + ld(Rn, Address(Rn)); + li(t0, 1); // set carry flag, i.e. no borrow + align(16); + bind(loop); { + notr(Rn, Rn); + add(Rm, Rm, t0); + add(Rm, Rm, Rn); + sltu(t0, Rm, Rn); + slli(Rn, i, LogBytesPerWord); // Rn as temp register + add(Rn, Pm_base, Rn); + sd(Rm, Address(Rn)); + add(i, i, 1); + slli(Rn, i, LogBytesPerWord); + add(Rm, Pm_base, Rn); + ld(Rm, Address(Rm)); + add(Rn, Pn_base, Rn); + ld(Rn, Address(Rn)); + sub(cnt, cnt, 1); + } bnez(cnt, loop); + addi(tmp0, tmp0, -1); + add(tmp0, tmp0, t0); + } bnez(tmp0, again); + } bind(post); + } + + // Move memory at s to d, reversing words. + // Increments d to end of copied memory + // Destroys tmp1, tmp2 + // Preserves len + // Leaves s pointing to the address which was in d at start + void reverse(Register d, Register s, Register len, Register tmp1, Register tmp2) { + assert(tmp1 < x28 && tmp2 < x28, "register corruption"); + + slli(tmp1, len, LogBytesPerWord); + add(s, s, tmp1); + mv(tmp1, len); + unroll_2(tmp1, &MontgomeryMultiplyGenerator::reverse1, d, s, tmp2); + slli(tmp1, len, LogBytesPerWord); + sub(s, d, tmp1); + } + // [63...0] -> [31...0][63...32] + void reverse1(Register d, Register s, Register tmp) { + addi(s, s, -wordSize); + ld(tmp, Address(s)); + ror_imm(tmp, tmp, 32, t0); + sd(tmp, Address(d)); + addi(d, d, wordSize); + } + + void step_squaring() { + // An extra ACC + step(); + acc(Rhi_ab, Rlo_ab, tmp0, tmp1, tmp2); + } + + void last_squaring(Register i) { + Label dont; + // if ((i & 1) == 0) { + andi(t0, i, 0x1); + bnez(t0, dont); { + // MACC(Ra, Rb, tmp0, tmp1, tmp2); + // Ra = *++Pa; + // Rb = *--Pb; + mulhu(Rhi_ab, Ra, Rb); + mul(Rlo_ab, Ra, Rb); + acc(Rhi_ab, Rlo_ab, tmp0, tmp1, tmp2); + } bind(dont); + } + + void extra_step_squaring() { + acc(Rhi_mn, Rlo_mn, tmp0, tmp1, tmp2); // The pending m*n + + // MACC(Rm, Rn, tmp0, tmp1, tmp2); + // Rm = *++Pm; + // Rn = *--Pn; + mulhu(Rhi_mn, Rm, Rn); + mul(Rlo_mn, Rm, Rn); + addi(Pm, Pm, wordSize); + ld(Rm, Address(Pm)); + addi(Pn, Pn, -wordSize); + ld(Rn, Address(Pn)); + } + + void post1_squaring() { + acc(Rhi_mn, Rlo_mn, tmp0, tmp1, tmp2); // The pending m*n + + // *Pm = Rm = tmp0 * inv; + mul(Rm, tmp0, inv); + sd(Rm, Address(Pm)); + + // MACC(Rm, Rn, tmp0, tmp1, tmp2); + // tmp0 = tmp1; tmp1 = tmp2; tmp2 = 0; + mulhu(Rhi_mn, Rm, Rn); + +#ifndef PRODUCT + // assert(m[i] * n[0] + tmp0 == 0, "broken Montgomery multiply"); + { + mul(Rlo_mn, Rm, Rn); + add(Rlo_mn, tmp0, Rlo_mn); + Label ok; + beqz(Rlo_mn, ok); { + stop("broken Montgomery multiply"); + } bind(ok); + } +#endif + // We have very carefully set things up so that + // m[i]*n[0] + tmp0 == 0 (mod b), so we don't have to calculate + // the lower half of Rm * Rn because we know the result already: + // it must be -tmp0. tmp0 + (-tmp0) must generate a carry iff + // tmp0 != 0. So, rather than do a mul and a cad we just set + // the carry flag iff tmp0 is nonzero. + // + // mul(Rlo_mn, Rm, Rn); + // cad(zr, tmp, Rlo_mn); + addi(t0, tmp0, -1); + sltu(t0, t0, tmp0); // Set carry iff tmp0 is nonzero + cadc(tmp0, tmp1, Rhi_mn, t0); + adc(tmp1, tmp2, zr, t0); + mv(tmp2, zr); + } + + // use t0 as carry + void acc(Register Rhi, Register Rlo, + Register tmp0, Register tmp1, Register tmp2) { + cad(tmp0, tmp0, Rlo, t0); + cadc(tmp1, tmp1, Rhi, t0); + adc(tmp2, tmp2, zr, t0); + } + + public: + /** + * Fast Montgomery multiplication. The derivation of the + * algorithm is in A Cryptographic Library for the Motorola + * DSP56000, Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237. + * + * Arguments: + * + * Inputs for multiplication: + * c_rarg0 - int array elements a + * c_rarg1 - int array elements b + * c_rarg2 - int array elements n (the modulus) + * c_rarg3 - int length + * c_rarg4 - int inv + * c_rarg5 - int array elements m (the result) + * + * Inputs for squaring: + * c_rarg0 - int array elements a + * c_rarg1 - int array elements n (the modulus) + * c_rarg2 - int length + * c_rarg3 - int inv + * c_rarg4 - int array elements m (the result) + * + */ + address generate_multiply() { + Label argh, nothing; + bind(argh); + stop("MontgomeryMultiply total_allocation must be <= 8192"); + + align(CodeEntryAlignment); + address entry = pc(); + + beqz(Rlen, nothing); + + enter(); + + // Make room. + li(Ra, 512); + bgt(Rlen, Ra, argh); + slli(Ra, Rlen, exact_log2(4 * sizeof(jint))); + sub(Ra, sp, Ra); + andi(sp, Ra, -2 * wordSize); + + srliw(Rlen, Rlen, 1); // length in longwords = len/2 + + { + // Copy input args, reversing as we go. We use Ra as a + // temporary variable. + reverse(Ra, Pa_base, Rlen, Ri, Rj); + if (!_squaring) + reverse(Ra, Pb_base, Rlen, Ri, Rj); + reverse(Ra, Pn_base, Rlen, Ri, Rj); + } + + // Push all call-saved registers and also Pm_base which we'll need + // at the end. + save_regs(); + +#ifndef PRODUCT + // assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply"); + { + ld(Rn, Address(Pn_base)); + mul(Rlo_mn, Rn, inv); + li(t0, -1); + Label ok; + beq(Rlo_mn, t0, ok); + stop("broken inverse in Montgomery multiply"); + bind(ok); + } +#endif + + mv(Pm_base, Ra); + + mv(tmp0, zr); + mv(tmp1, zr); + mv(tmp2, zr); + + block_comment("for (int i = 0; i < len; i++) {"); + mv(Ri, zr); { + Label loop, end; + bge(Ri, Rlen, end); + + bind(loop); + pre1(Ri); + + block_comment(" for (j = i; j; j--) {"); { + mv(Rj, Ri); + unroll_2(Rj, &MontgomeryMultiplyGenerator::step); + } block_comment(" } // j"); + + post1(); + addw(Ri, Ri, 1); + blt(Ri, Rlen, loop); + bind(end); + block_comment("} // i"); + } + + block_comment("for (int i = len; i < 2*len; i++) {"); + mv(Ri, Rlen); { + Label loop, end; + slli(t0, Rlen, 1); + bge(Ri, t0, end); + + bind(loop); + pre2(Ri, Rlen); + + block_comment(" for (j = len*2-i-1; j; j--) {"); { + slliw(Rj, Rlen, 1); + subw(Rj, Rj, Ri); + subw(Rj, Rj, 1); + unroll_2(Rj, &MontgomeryMultiplyGenerator::step); + } block_comment(" } // j"); + + post2(Ri, Rlen); + addw(Ri, Ri, 1); + slli(t0, Rlen, 1); + blt(Ri, t0, loop); + bind(end); + } + block_comment("} // i"); + + normalize(Rlen); + + mv(Ra, Pm_base); // Save Pm_base in Ra + restore_regs(); // Restore caller's Pm_base + + // Copy our result into caller's Pm_base + reverse(Pm_base, Ra, Rlen, Ri, Rj); + + leave(); + bind(nothing); + ret(); + + return entry; + } + + /** + * + * Arguments: + * + * Inputs: + * c_rarg0 - int array elements a + * c_rarg1 - int array elements n (the modulus) + * c_rarg2 - int length + * c_rarg3 - int inv + * c_rarg4 - int array elements m (the result) + * + */ + address generate_square() { + Label argh; + bind(argh); + stop("MontgomeryMultiply total_allocation must be <= 8192"); + + align(CodeEntryAlignment); + address entry = pc(); + + enter(); + + // Make room. + li(Ra, 512); + bgt(Rlen, Ra, argh); + slli(Ra, Rlen, exact_log2(4 * sizeof(jint))); + sub(Ra, sp, Ra); + andi(sp, Ra, -2 * wordSize); + + srliw(Rlen, Rlen, 1); // length in longwords = len/2 + + { + // Copy input args, reversing as we go. We use Ra as a + // temporary variable. + reverse(Ra, Pa_base, Rlen, Ri, Rj); + reverse(Ra, Pn_base, Rlen, Ri, Rj); + } + + // Push all call-saved registers and also Pm_base which we'll need + // at the end. + save_regs(); + + mv(Pm_base, Ra); + + mv(tmp0, zr); + mv(tmp1, zr); + mv(tmp2, zr); + + block_comment("for (int i = 0; i < len; i++) {"); + mv(Ri, zr); { + Label loop, end; + bind(loop); + bge(Ri, Rlen, end); + + pre1(Ri); + + block_comment("for (j = (i+1)/2; j; j--) {"); { + addi(Rj, Ri, 1); + srliw(Rj, Rj, 1); + unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring); + } block_comment(" } // j"); + + last_squaring(Ri); + + block_comment(" for (j = i/2; j; j--) {"); { + srliw(Rj, Ri, 1); + unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring); + } block_comment(" } // j"); + + post1_squaring(); + addi(Ri, Ri, 1); + blt(Ri, Rlen, loop); + + bind(end); + block_comment("} // i"); + } + + block_comment("for (int i = len; i < 2*len; i++) {"); + mv(Ri, Rlen); { + Label loop, end; + bind(loop); + slli(t0, Rlen, 1); + bge(Ri, t0, end); + + pre2(Ri, Rlen); + + block_comment(" for (j = (2*len-i-1)/2; j; j--) {"); { + slli(Rj, Rlen, 1); + sub(Rj, Rj, Ri); + sub(Rj, Rj, 1); + srliw(Rj, Rj, 1); + unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring); + } block_comment(" } // j"); + + last_squaring(Ri); + + block_comment(" for (j = (2*len-i)/2; j; j--) {"); { + slli(Rj, Rlen, 1); + sub(Rj, Rj, Ri); + srliw(Rj, Rj, 1); + unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring); + } block_comment(" } // j"); + + post2(Ri, Rlen); + addi(Ri, Ri, 1); + slli(t0, Rlen, 1); + blt(Ri, t0, loop); + + bind(end); + block_comment("} // i"); + } + + normalize(Rlen); + + mv(Ra, Pm_base); // Save Pm_base in Ra + restore_regs(); // Restore caller's Pm_base + + // Copy our result into caller's Pm_base + reverse(Pm_base, Ra, Rlen, Ri, Rj); + + leave(); + ret(); + + return entry; + } + }; +#endif // COMPILER2 + + // Continuation point for throwing of implicit exceptions that are + // not handled in the current activation. Fabricates an exception + // oop and initiates normal exception dispatching in this + // frame. Since we need to preserve callee-saved values (currently + // only for C2, but done for C1 as well) we need a callee-saved oop + // map and therefore have to make these stubs into RuntimeStubs + // rather than BufferBlobs. If the compiler needs all registers to + // be preserved between the fault point and the exception handler + // then it must assume responsibility for that in + // AbstractCompiler::continuation_for_implicit_null_exception or + // continuation_for_implicit_division_by_zero_exception. All other + // implicit exceptions (e.g., NullPointerException or + // AbstractMethodError on entry) are either at call sites or + // otherwise assume that stack unwinding will be initiated, so + // caller saved registers were assumed volatile in the compiler. + +#undef __ +#define __ masm-> + + address generate_throw_exception(const char* name, + address runtime_entry, + Register arg1 = noreg, + Register arg2 = noreg) { + // Information about frame layout at time of blocking runtime call. + // Note that we only have to preserve callee-saved registers since + // the compilers are responsible for supplying a continuation point + // if they expect all registers to be preserved. + // n.b. riscv asserts that frame::arg_reg_save_area_bytes == 0 + assert_cond(runtime_entry != NULL); + enum layout { + fp_off = 0, + fp_off2, + return_off, + return_off2, + framesize // inclusive of return address + }; + + const int insts_size = 512; + const int locs_size = 64; + + CodeBuffer code(name, insts_size, locs_size); + OopMapSet* oop_maps = new OopMapSet(); + MacroAssembler* masm = new MacroAssembler(&code); + assert_cond(oop_maps != NULL && masm != NULL); + + address start = __ pc(); + + // This is an inlined and slightly modified version of call_VM + // which has the ability to fetch the return PC out of + // thread-local storage and also sets up last_Java_sp slightly + // differently than the real call_VM + + __ enter(); // Save FP and RA before call + + assert(is_even(framesize / 2), "sp not 16-byte aligned"); + + // ra and fp are already in place + __ addi(sp, fp, 0 - ((unsigned)framesize << LogBytesPerInt)); // prolog + + int frame_complete = __ pc() - start; + + // Set up last_Java_sp and last_Java_fp + address the_pc = __ pc(); + __ set_last_Java_frame(sp, fp, the_pc, t0); + + // Call runtime + if (arg1 != noreg) { + assert(arg2 != c_rarg1, "clobbered"); + __ mv(c_rarg1, arg1); + } + if (arg2 != noreg) { + __ mv(c_rarg2, arg2); + } + __ mv(c_rarg0, xthread); + BLOCK_COMMENT("call runtime_entry"); + int32_t offset = 0; + __ movptr_with_offset(t0, runtime_entry, offset); + __ jalr(x1, t0, offset); + + // Generate oop map + OopMap* map = new OopMap(framesize, 0); + assert_cond(map != NULL); + + oop_maps->add_gc_map(the_pc - start, map); + + __ reset_last_Java_frame(true); + + __ leave(); + + // check for pending exceptions +#ifdef ASSERT + Label L; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ bnez(t0, L); + __ should_not_reach_here(); + __ bind(L); +#endif // ASSERT + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + + + // codeBlob framesize is in words (not VMRegImpl::slot_size) + RuntimeStub* stub = + RuntimeStub::new_runtime_stub(name, + &code, + frame_complete, + (framesize >> (LogBytesPerWord - LogBytesPerInt)), + oop_maps, false); + assert(stub != NULL, "create runtime stub fail!"); + return stub->entry_point(); + } + + // Initialization + void generate_initial() { + // Generate initial stubs and initializes the entry points + + // entry points that exist in all platforms Note: This is code + // that could be shared among different platforms - however the + // benefit seems to be smaller than the disadvantage of having a + // much more complicated generator structure. See also comment in + // stubRoutines.hpp. + + StubRoutines::_forward_exception_entry = generate_forward_exception(); + + StubRoutines::_call_stub_entry = + generate_call_stub(StubRoutines::_call_stub_return_address); + + // is referenced by megamorphic call + StubRoutines::_catch_exception_entry = generate_catch_exception(); + + // Build this early so it's available for the interpreter. + StubRoutines::_throw_StackOverflowError_entry = + generate_throw_exception("StackOverflowError throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime::throw_StackOverflowError)); + StubRoutines::_throw_delayed_StackOverflowError_entry = + generate_throw_exception("delayed StackOverflowError throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime::throw_delayed_StackOverflowError)); + // Safefetch stubs. + generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, + &StubRoutines::_safefetch32_fault_pc, + &StubRoutines::_safefetch32_continuation_pc); + generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry, + &StubRoutines::_safefetchN_fault_pc, + &StubRoutines::_safefetchN_continuation_pc); + } + + void generate_all() { + // support for verify_oop (must happen after universe_init) + StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); + StubRoutines::_throw_AbstractMethodError_entry = + generate_throw_exception("AbstractMethodError throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime:: + throw_AbstractMethodError)); + + StubRoutines::_throw_IncompatibleClassChangeError_entry = + generate_throw_exception("IncompatibleClassChangeError throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime:: + throw_IncompatibleClassChangeError)); + + StubRoutines::_throw_NullPointerException_at_call_entry = + generate_throw_exception("NullPointerException at call throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime:: + throw_NullPointerException_at_call)); + // arraycopy stubs used by compilers + generate_arraycopy_stubs(); + +#ifdef COMPILER2 + if (UseMulAddIntrinsic) { + StubRoutines::_mulAdd = generate_mulAdd(); + } + + if (UseMultiplyToLenIntrinsic) { + StubRoutines::_multiplyToLen = generate_multiplyToLen(); + } + + if (UseSquareToLenIntrinsic) { + StubRoutines::_squareToLen = generate_squareToLen(); + } + + if (UseMontgomeryMultiplyIntrinsic) { + StubCodeMark mark(this, "StubRoutines", "montgomeryMultiply"); + MontgomeryMultiplyGenerator g(_masm, /*squaring*/false); + StubRoutines::_montgomeryMultiply = g.generate_multiply(); + } + + if (UseMontgomerySquareIntrinsic) { + StubCodeMark mark(this, "StubRoutines", "montgomerySquare"); + MontgomeryMultiplyGenerator g(_masm, /*squaring*/true); + StubRoutines::_montgomerySquare = g.generate_square(); + } + + if (UseRVVForBigIntegerShiftIntrinsics) { + StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); + StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); + } +#endif + + generate_compare_long_strings(); + + generate_string_indexof_stubs(); + + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm != NULL) { + StubRoutines::riscv::_method_entry_barrier = generate_method_entry_barrier(); + } + + StubRoutines::riscv::set_completed(); + } + + public: + StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { + if (all) { + generate_all(); + } else { + generate_initial(); + } + } + + ~StubGenerator() {} +}; // end class declaration + +#define UCM_TABLE_MAX_ENTRIES 8 +void StubGenerator_generate(CodeBuffer* code, bool all) { + if (UnsafeCopyMemory::_table == NULL) { + UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES); + } + + StubGenerator g(code, all); +} diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..395a2d338e4c32424fcfd0507c309695eeca6e3b --- /dev/null +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/deoptimization.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +// Implementation of the platform-specific part of StubRoutines - for +// a description of how to extend it, see the stubRoutines.hpp file. + +address StubRoutines::riscv::_get_previous_sp_entry = NULL; + +address StubRoutines::riscv::_f2i_fixup = NULL; +address StubRoutines::riscv::_f2l_fixup = NULL; +address StubRoutines::riscv::_d2i_fixup = NULL; +address StubRoutines::riscv::_d2l_fixup = NULL; +address StubRoutines::riscv::_float_sign_mask = NULL; +address StubRoutines::riscv::_float_sign_flip = NULL; +address StubRoutines::riscv::_double_sign_mask = NULL; +address StubRoutines::riscv::_double_sign_flip = NULL; +address StubRoutines::riscv::_zero_blocks = NULL; +address StubRoutines::riscv::_compare_long_string_LL = NULL; +address StubRoutines::riscv::_compare_long_string_UU = NULL; +address StubRoutines::riscv::_compare_long_string_LU = NULL; +address StubRoutines::riscv::_compare_long_string_UL = NULL; +address StubRoutines::riscv::_string_indexof_linear_ll = NULL; +address StubRoutines::riscv::_string_indexof_linear_uu = NULL; +address StubRoutines::riscv::_string_indexof_linear_ul = NULL; +address StubRoutines::riscv::_large_byte_array_inflate = NULL; +address StubRoutines::riscv::_method_entry_barrier = NULL; + +bool StubRoutines::riscv::_completed = false; diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..51f07819c33a125232b94b05692fed727b10e068 --- /dev/null +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_STUBROUTINES_RISCV_HPP +#define CPU_RISCV_STUBROUTINES_RISCV_HPP + +// This file holds the platform specific parts of the StubRoutines +// definition. See stubRoutines.hpp for a description on how to +// extend it. + +static bool returns_to_call_stub(address return_pc) { + return return_pc == _call_stub_return_address; +} + +enum platform_dependent_constants { + code_size1 = 19000, // simply increase if too small (assembler will crash if too small) + code_size2 = 28000 // simply increase if too small (assembler will crash if too small) +}; + +class riscv { + friend class StubGenerator; + + private: + static address _get_previous_sp_entry; + + static address _f2i_fixup; + static address _f2l_fixup; + static address _d2i_fixup; + static address _d2l_fixup; + + static address _float_sign_mask; + static address _float_sign_flip; + static address _double_sign_mask; + static address _double_sign_flip; + + static address _zero_blocks; + + static address _compare_long_string_LL; + static address _compare_long_string_LU; + static address _compare_long_string_UL; + static address _compare_long_string_UU; + static address _string_indexof_linear_ll; + static address _string_indexof_linear_uu; + static address _string_indexof_linear_ul; + static address _large_byte_array_inflate; + + static address _method_entry_barrier; + + static bool _completed; + + public: + + static address get_previous_sp_entry() { + return _get_previous_sp_entry; + } + + static address f2i_fixup() { + return _f2i_fixup; + } + + static address f2l_fixup() { + return _f2l_fixup; + } + + static address d2i_fixup() { + return _d2i_fixup; + } + + static address d2l_fixup() { + return _d2l_fixup; + } + + static address float_sign_mask() { + return _float_sign_mask; + } + + static address float_sign_flip() { + return _float_sign_flip; + } + + static address double_sign_mask() { + return _double_sign_mask; + } + + static address double_sign_flip() { + return _double_sign_flip; + } + + static address zero_blocks() { + return _zero_blocks; + } + + static address compare_long_string_LL() { + return _compare_long_string_LL; + } + + static address compare_long_string_LU() { + return _compare_long_string_LU; + } + + static address compare_long_string_UL() { + return _compare_long_string_UL; + } + + static address compare_long_string_UU() { + return _compare_long_string_UU; + } + + static address string_indexof_linear_ul() { + return _string_indexof_linear_ul; + } + + static address string_indexof_linear_ll() { + return _string_indexof_linear_ll; + } + + static address string_indexof_linear_uu() { + return _string_indexof_linear_uu; + } + + static address large_byte_array_inflate() { + return _large_byte_array_inflate; + } + + static address method_entry_barrier() { + return _method_entry_barrier; + } + + static bool complete() { + return _completed; + } + + static void set_completed() { + _completed = true; + } +}; + +#endif // CPU_RISCV_STUBROUTINES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6537b2dbd94137f8a889d1ad728fa185adf01f4b --- /dev/null +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -0,0 +1,1794 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "interpreter/bytecodeHistogram.hpp" +#include "interpreter/bytecodeTracer.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/templateInterpreterGenerator.hpp" +#include "interpreter/templateTable.hpp" +#include "memory/resourceArea.hpp" +#include "oops/arrayOop.hpp" +#include "oops/method.hpp" +#include "oops/methodData.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/arguments.hpp" +#include "runtime/deoptimization.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/timer.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" +#include + +#ifndef PRODUCT +#include "oops/method.hpp" +#endif // !PRODUCT + +// Size of interpreter code. Increase if too small. Interpreter will +// fail with a guarantee ("not enough space for interpreter generation"); +// if too small. +// Run with +PrintInterpreter to get the VM to print out the size. +// Max size with JVMTI +int TemplateInterpreter::InterpreterCodeSize = 256 * 1024; + +#define __ _masm-> + +//----------------------------------------------------------------------------- + +address TemplateInterpreterGenerator::generate_slow_signature_handler() { + address entry = __ pc(); + + __ andi(esp, esp, -16); + __ mv(c_rarg3, esp); + // xmethod + // xlocals + // c_rarg3: first stack arg - wordSize + // adjust sp + + __ addi(sp, c_rarg3, -18 * wordSize); + __ addi(sp, sp, -2 * wordSize); + __ sd(ra, Address(sp, 0)); + + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::slow_signature_handler), + xmethod, xlocals, c_rarg3); + + // x10: result handler + + // Stack layout: + // sp: return address <- sp + // 1 garbage + // 8 integer args (if static first is unused) + // 1 float/double identifiers + // 8 double args + // stack args <- esp + // garbage + // expression stack bottom + // bcp (NULL) + // ... + + // Restore ra + __ ld(ra, Address(sp, 0)); + __ addi(sp, sp , 2 * wordSize); + + // Do FP first so we can use c_rarg3 as temp + __ lwu(c_rarg3, Address(sp, 9 * wordSize)); // float/double identifiers + + for (int i = 0; i < Argument::n_float_register_parameters_c; i++) { + const FloatRegister r = g_FPArgReg[i]; + Label d, done; + + __ andi(t0, c_rarg3, 1UL << i); + __ bnez(t0, d); + __ flw(r, Address(sp, (10 + i) * wordSize)); + __ j(done); + __ bind(d); + __ fld(r, Address(sp, (10 + i) * wordSize)); + __ bind(done); + } + + // c_rarg0 contains the result from the call of + // InterpreterRuntime::slow_signature_handler so we don't touch it + // here. It will be loaded with the JNIEnv* later. + for (int i = 1; i < Argument::n_int_register_parameters_c; i++) { + const Register rm = g_INTArgReg[i]; + __ ld(rm, Address(sp, i * wordSize)); + } + + __ addi(sp, sp, 18 * wordSize); + __ ret(); + + return entry; +} + +// Various method entries +address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { + // xmethod: Method* + // x30: sender sp + // esp: args + + if (!InlineIntrinsics) { + return NULL; // Generate a vanilla entry + } + + // These don't need a safepoint check because they aren't virtually + // callable. We won't enter these intrinsics from compiled code. + // If in the future we added an intrinsic which was virtually callable + // we'd have to worry about how to safepoint so that this code is used. + + // mathematical functions inlined by compiler + // (interpreter must provide identical implementation + // in order to avoid monotonicity bugs when switching + // from interpreter to compiler in the middle of some + // computation) + // + // stack: + // [ arg ] <-- esp + // [ arg ] + // retaddr in ra + + address fn = NULL; + address entry_point = NULL; + Register continuation = ra; + switch (kind) { + case Interpreter::java_lang_math_abs: + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ fabs_d(f10, f10); + __ mv(sp, x30); // Restore caller's SP + break; + case Interpreter::java_lang_math_sqrt: + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ fsqrt_d(f10, f10); + __ mv(sp, x30); + break; + case Interpreter::java_lang_math_sin : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dsin() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dsin()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_cos : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dcos() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dcos()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_tan : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dtan() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dtan()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_log : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dlog() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_log10 : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dlog10() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog10()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_exp : + entry_point = __ pc(); + __ fld(f10, Address(esp)); + __ mv(sp, x30); + __ mv(x9, ra); + continuation = x9; // The first callee-saved register + if (StubRoutines::dexp() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dexp()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_pow : + entry_point = __ pc(); + __ mv(x9, ra); + continuation = x9; + __ fld(f10, Address(esp, 2 * Interpreter::stackElementSize)); + __ fld(f11, Address(esp)); + __ mv(sp, x30); + if (StubRoutines::dpow() == NULL) { + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); + } else { + fn = CAST_FROM_FN_PTR(address, StubRoutines::dpow()); + } + __ mv(t0, fn); + __ jalr(t0); + break; + case Interpreter::java_lang_math_fmaD : + if (UseFMA) { + entry_point = __ pc(); + __ fld(f10, Address(esp, 4 * Interpreter::stackElementSize)); + __ fld(f11, Address(esp, 2 * Interpreter::stackElementSize)); + __ fld(f12, Address(esp)); + __ fmadd_d(f10, f10, f11, f12); + __ mv(sp, x30); // Restore caller's SP + } + break; + case Interpreter::java_lang_math_fmaF : + if (UseFMA) { + entry_point = __ pc(); + __ flw(f10, Address(esp, 2 * Interpreter::stackElementSize)); + __ flw(f11, Address(esp, Interpreter::stackElementSize)); + __ flw(f12, Address(esp)); + __ fmadd_s(f10, f10, f11, f12); + __ mv(sp, x30); // Restore caller's SP + } + break; + default: + ; + } + if (entry_point != NULL) { + __ jr(continuation); + } + + return entry_point; +} + +// Abstract method entry +// Attempt to execute abstract method. Throw exception +address TemplateInterpreterGenerator::generate_abstract_entry(void) { + // xmethod: Method* + // x30: sender SP + + address entry_point = __ pc(); + + // abstract method entry + + // pop return address, reset last_sp to NULL + __ empty_expression_stack(); + __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) + + // throw exception + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_AbstractMethodErrorWithMethod), + xmethod); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + + return entry_point; +} + +address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { + address entry = __ pc(); + +#ifdef ASSERT + { + Label L; + __ ld(t0, Address(fp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); + __ mv(t1, sp); + // maximal sp for current fp (stack grows negative) + // check if frame is complete + __ bge(t0, t1, L); + __ stop ("interpreter frame not set up"); + __ bind(L); + } +#endif // ASSERT + // Restore bcp under the assumption that the current frame is still + // interpreted + __ restore_bcp(); + + // expression stack must be empty before entering the VM if an + // exception happened + __ empty_expression_stack(); + // throw exception + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_StackOverflowError)); + return entry; +} + +address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler() { + address entry = __ pc(); + // expression stack must be empty before entering the VM if an + // exception happened + __ empty_expression_stack(); + // setup parameters + + // convention: expect aberrant index in register x11 + __ zero_extend(c_rarg2, x11, 32); + // convention: expect array in register x13 + __ mv(c_rarg1, x13); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime:: + throw_ArrayIndexOutOfBoundsException), + c_rarg1, c_rarg2); + return entry; +} + +address TemplateInterpreterGenerator::generate_ClassCastException_handler() { + address entry = __ pc(); + + // object is at TOS + __ pop_reg(c_rarg1); + + // expression stack must be empty before entering the VM if an + // exception happened + __ empty_expression_stack(); + + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime:: + throw_ClassCastException), + c_rarg1); + return entry; +} + +address TemplateInterpreterGenerator::generate_exception_handler_common( + const char* name, const char* message, bool pass_oop) { + assert(!pass_oop || message == NULL, "either oop or message but not both"); + address entry = __ pc(); + if (pass_oop) { + // object is at TOS + __ pop_reg(c_rarg2); + } + // expression stack must be empty before entering the VM if an + // exception happened + __ empty_expression_stack(); + // setup parameters + __ la(c_rarg1, Address((address)name)); + if (pass_oop) { + __ call_VM(x10, CAST_FROM_FN_PTR(address, + InterpreterRuntime:: + create_klass_exception), + c_rarg1, c_rarg2); + } else { + // kind of lame ExternalAddress can't take NULL because + // external_word_Relocation will assert. + if (message != NULL) { + __ la(c_rarg2, Address((address)message)); + } else { + __ mv(c_rarg2, NULL_WORD); + } + __ call_VM(x10, + CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), + c_rarg1, c_rarg2); + } + // throw exception + __ j(address(Interpreter::throw_exception_entry())); + return entry; +} + +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { + address entry = __ pc(); + + // Restore stack bottom in case i2c adjusted stack + __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + // and NULL it as marker that esp is now tos until next java call + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ restore_bcp(); + __ restore_locals(); + __ restore_constant_pool_cache(); + __ get_method(xmethod); + + if (state == atos) { + Register obj = x10; + Register mdp = x11; + Register tmp = x12; + __ ld(mdp, Address(xmethod, Method::method_data_offset())); + __ profile_return_type(mdp, obj, tmp); + } + + // Pop N words from the stack + __ get_cache_and_index_at_bcp(x11, x12, 1, index_size); + __ ld(x11, Address(x11, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); + __ andi(x11, x11, ConstantPoolCacheEntry::parameter_size_mask); + + __ shadd(esp, x11, esp, t0, 3); + + // Restore machine SP + __ ld(t0, Address(xmethod, Method::const_offset())); + __ lhu(t0, Address(t0, ConstMethod::max_stack_offset())); + __ addi(t0, t0, frame::interpreter_frame_monitor_size() + 2); + __ ld(t1, + Address(fp, frame::interpreter_frame_initial_sp_offset * wordSize)); + __ slli(t0, t0, 3); + __ sub(t0, t1, t0); + __ andi(sp, t0, -16); + + __ check_and_handle_popframe(xthread); + __ check_and_handle_earlyret(xthread); + + __ get_dispatch(); + __ dispatch_next(state, step); + + return entry; +} + +address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, + int step, + address continuation) { + address entry = __ pc(); + __ restore_bcp(); + __ restore_locals(); + __ restore_constant_pool_cache(); + __ get_method(xmethod); + __ get_dispatch(); + + // Calculate stack limit + __ ld(t0, Address(xmethod, Method::const_offset())); + __ lhu(t0, Address(t0, ConstMethod::max_stack_offset())); + __ addi(t0, t0, frame::interpreter_frame_monitor_size() + 2); + __ ld(t1, Address(fp, frame::interpreter_frame_initial_sp_offset * wordSize)); + __ slli(t0, t0, 3); + __ sub(t0, t1, t0); + __ andi(sp, t0, -16); + + // Restore expression stack pointer + __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + // NULL last_sp until next java call + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + + // handle exceptions + { + Label L; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ beqz(t0, L); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_pending_exception)); + __ should_not_reach_here(); + __ bind(L); + } + + if (continuation == NULL) { + __ dispatch_next(state, step); + } else { + __ jump_to_entry(continuation); + } + return entry; +} + +address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type) { + address entry = __ pc(); + if (type == T_OBJECT) { + // retrieve result from frame + __ ld(x10, Address(fp, frame::interpreter_frame_oop_temp_offset * wordSize)); + // and verify it + __ verify_oop(x10); + } else { + __ cast_primitive_type(type, x10); + } + + __ ret(); // return from result handler + return entry; +} + +address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, + address runtime_entry) { + assert_cond(runtime_entry != NULL); + address entry = __ pc(); + __ push(state); + __ call_VM(noreg, runtime_entry); + __ fence(0xf, 0xf); + __ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos)); + return entry; +} + +// Helpers for commoning out cases in the various type of method entries. +// + + +// increment invocation count & check for overflow +// +// Note: checking for negative value instead of overflow +// so we have a 'sticky' overflow test +// +// xmethod: method +// +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? + __ ld(x10, Address(xmethod, Method::method_data_offset())); + __ beqz(x10, no_mdo); + // Increment counter in the MDO + const Address mdo_invocation_counter(x10, in_bytes(MethodData::invocation_counter_offset()) + + in_bytes(InvocationCounter::counter_offset())); + const Address mask(x10, in_bytes(MethodData::invoke_mask_offset())); + __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, t0, t1, false, overflow); + __ j(done); + } + __ bind(no_mdo); + // Increment counter in MethodCounters + const Address invocation_counter(t1, + MethodCounters::invocation_counter_offset() + + InvocationCounter::counter_offset()); + __ get_method_counters(xmethod, t1, done); + const Address mask(t1, in_bytes(MethodCounters::invoke_mask_offset())); + __ increment_mask_and_jump(invocation_counter, increment, mask, t0, x11, false, overflow); + __ bind(done); +} + +void TemplateInterpreterGenerator::generate_counter_overflow(Label& do_continue) { + __ mv(c_rarg1, zr); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), c_rarg1); + __ j(do_continue); +} + +// See if we've got enough room on the stack for locals plus overhead +// below JavaThread::stack_overflow_limit(). If not, throw a StackOverflowError +// without going through the signal handler, i.e., reserved and yellow zones +// will not be made usable. The shadow zone must suffice to handle the +// overflow. +// The expression stack grows down incrementally, so the normal guard +// page mechanism will work for that. +// +// NOTE: Since the additional locals are also always pushed (wasn't +// obvious in generate_method_entry) so the guard should work for them +// too. +// +// Args: +// x13: number of additional locals this frame needs (what we must check) +// xmethod: Method* +// +// Kills: +// x10 +void TemplateInterpreterGenerator::generate_stack_overflow_check(void) { + + // monitor entry size: see picture of stack set + // (generate_method_entry) and frame_amd64.hpp + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + + // total overhead size: entry_size + (saved fp through expr stack + // bottom). be sure to change this if you add/subtract anything + // to/from the overhead area + const int overhead_size = + -(frame::interpreter_frame_initial_sp_offset * wordSize) + entry_size; + + const int page_size = os::vm_page_size(); + + Label after_frame_check; + + // see if the frame is greater than one page in size. If so, + // then we need to verify there is enough stack space remaining + // for the additional locals. + __ mv(t0, (page_size - overhead_size) / Interpreter::stackElementSize); + __ bleu(x13, t0, after_frame_check); + + // compute sp as if this were going to be the last frame on + // the stack before the red zone + + // locals + overhead, in bytes + __ mv(x10, overhead_size); + __ shadd(x10, x13, x10, t0, Interpreter::logStackElementSize); // 2 slots per parameter. + + const Address stack_limit(xthread, JavaThread::stack_overflow_limit_offset()); + __ ld(t0, stack_limit); + +#ifdef ASSERT + Label limit_okay; + // Verify that thread stack limit is non-zero. + __ bnez(t0, limit_okay); + __ stop("stack overflow limit is zero"); + __ bind(limit_okay); +#endif + + // Add stack limit to locals. + __ add(x10, x10, t0); + + // Check against the current stack bottom. + __ bgtu(sp, x10, after_frame_check); + + // Remove the incoming args, peeling the machine SP back to where it + // was in the caller. This is not strictly necessary, but unless we + // do so the stack frame may have a garbage FP; this ensures a + // correct call stack that we can always unwind. The ANDI should be + // unnecessary because the sender SP in x30 is always aligned, but + // it doesn't hurt. + __ andi(sp, x30, -16); + + // Note: the restored frame is not necessarily interpreted. + // Use the shared runtime version of the StackOverflowError. + assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "stub not yet generated"); + __ far_jump(RuntimeAddress(StubRoutines::throw_StackOverflowError_entry())); + + // all done with frame size check + __ bind(after_frame_check); +} + +// Allocate monitor and lock method (asm interpreter) +// +// Args: +// xmethod: Method* +// xlocals: locals +// +// Kills: +// x10 +// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs) +// t0, t1 (temporary regs) +void TemplateInterpreterGenerator::lock_method() { + // synchronize method + const Address access_flags(xmethod, Method::access_flags_offset()); + const Address monitor_block_top(fp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + +#ifdef ASSERT + __ lwu(x10, access_flags); + __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method doesn't need synchronization", false); +#endif // ASSERT + + // get synchronization object + { + Label done; + __ lwu(x10, access_flags); + __ andi(t0, x10, JVM_ACC_STATIC); + // get receiver (assume this is frequent case) + __ ld(x10, Address(xlocals, Interpreter::local_offset_in_bytes(0))); + __ beqz(t0, done); + __ load_mirror(x10, xmethod); + +#ifdef ASSERT + { + Label L; + __ bnez(x10, L); + __ stop("synchronization object is NULL"); + __ bind(L); + } +#endif // ASSERT + + __ bind(done); + } + + // add space for monitor & lock + __ add(sp, sp, - entry_size); // add space for a monitor entry + __ add(esp, esp, - entry_size); + __ mv(t0, esp); + __ sd(t0, monitor_block_top); // set new monitor block top + // store object + __ sd(x10, Address(esp, BasicObjectLock::obj_offset_in_bytes())); + __ mv(c_rarg1, esp); // object address + __ lock_object(c_rarg1); +} + +// Generate a fixed interpreter frame. This is identical setup for +// interpreted methods and for native methods hence the shared code. +// +// Args: +// ra: return address +// xmethod: Method* +// xlocals: pointer to locals +// xcpool: cp cache +// stack_pointer: previous sp +void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { + // initialize fixed part of activation frame + if (native_call) { + __ add(esp, sp, - 14 * wordSize); + __ mv(xbcp, zr); + __ add(sp, sp, - 14 * wordSize); + // add 2 zero-initialized slots for native calls + __ sd(zr, Address(sp, 13 * wordSize)); + __ sd(zr, Address(sp, 12 * wordSize)); + } else { + __ add(esp, sp, - 12 * wordSize); + __ ld(t0, Address(xmethod, Method::const_offset())); // get ConstMethod + __ add(xbcp, t0, in_bytes(ConstMethod::codes_offset())); // get codebase + __ add(sp, sp, - 12 * wordSize); + } + __ sd(xbcp, Address(sp, wordSize)); + __ sd(esp, Address(sp, 0)); + + if (ProfileInterpreter) { + Label method_data_continue; + __ ld(t0, Address(xmethod, Method::method_data_offset())); + __ beqz(t0, method_data_continue); + __ la(t0, Address(t0, in_bytes(MethodData::data_offset()))); + __ bind(method_data_continue); + } + + __ sd(xmethod, Address(sp, 7 * wordSize)); + __ sd(ProfileInterpreter ? t0 : zr, Address(sp, 6 * wordSize)); + + // Get mirror and store it in the frame as GC root for this Method* + __ load_mirror(t2, xmethod); + __ sd(zr, Address(sp, 5 * wordSize)); + __ sd(t2, Address(sp, 4 * wordSize)); + + __ ld(xcpool, Address(xmethod, Method::const_offset())); + __ ld(xcpool, Address(xcpool, ConstMethod::constants_offset())); + __ ld(xcpool, Address(xcpool, ConstantPool::cache_offset_in_bytes())); + __ sd(xcpool, Address(sp, 3 * wordSize)); + __ sd(xlocals, Address(sp, 2 * wordSize)); + + __ sd(ra, Address(sp, 11 * wordSize)); + __ sd(fp, Address(sp, 10 * wordSize)); + __ la(fp, Address(sp, 12 * wordSize)); // include ra & fp + + // set sender sp + // leave last_sp as null + __ sd(x30, Address(sp, 9 * wordSize)); + __ sd(zr, Address(sp, 8 * wordSize)); + + // Move SP out of the way + if (!native_call) { + __ ld(t0, Address(xmethod, Method::const_offset())); + __ lhu(t0, Address(t0, ConstMethod::max_stack_offset())); + __ add(t0, t0, frame::interpreter_frame_monitor_size() + 2); + __ slli(t0, t0, 3); + __ sub(t0, sp, t0); + __ andi(sp, t0, -16); + } +} + +// End of helpers + +// Various method entries +//------------------------------------------------------------------------------------------------------------------------ +// +// + +// Method entry for java.lang.ref.Reference.get. +address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { + // Code: _aload_0, _getfield, _areturn + // parameter size = 1 + // + // The code that gets generated by this routine is split into 2 parts: + // 1. The "intrinsified" code for G1 (or any SATB based GC), + // 2. The slow path - which is an expansion of the regular method entry. + // + // Notes:- + // * In the G1 code we do not check whether we need to block for + // a safepoint. If G1 is enabled then we must execute the specialized + // code for Reference.get (except when the Reference object is null) + // so that we can log the value in the referent field with an SATB + // update buffer. + // If the code for the getfield template is modified so that the + // G1 pre-barrier code is executed when the current method is + // Reference.get() then going through the normal method entry + // will be fine. + // * The G1 code can, however, check the receiver object (the instance + // of java.lang.Reference) and jump to the slow path if null. If the + // Reference object is null then we obviously cannot fetch the referent + // and so we don't need to call the G1 pre-barrier. Thus we can use the + // regular method entry code to generate the NPE. + // + // This code is based on generate_accessor_entry. + // + // xmethod: Method* + // x30: senderSP must preserve for slow path, set SP to it on fast path + + // ra is live. It must be saved around calls. + + address entry = __ pc(); + + const int referent_offset = java_lang_ref_Reference::referent_offset(); + guarantee(referent_offset > 0, "referent offset not initialized"); + + Label slow_path; + const Register local_0 = c_rarg0; + // Check if local 0 != NULL + // If the receiver is null then it is OK to jump to the slow path. + __ ld(local_0, Address(esp, 0)); + __ beqz(local_0, slow_path); + + __ mv(x9, x30); // Move senderSP to a callee-saved register + + // Load the value of the referent field. + const Address field_address(local_0, referent_offset); + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT, local_0, field_address, /*tmp1*/ t1, /*tmp2*/ t0); + + // areturn + __ andi(sp, x9, -16); // done with stack + __ ret(); + + // generate a vanilla interpreter entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals)); + return entry; +} + +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.update(int crc, int b) + */ +address TemplateInterpreterGenerator::generate_CRC32_update_entry() { + // TODO: Unimplemented generate_CRC32_update_entry + return 0; +} + +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len) + * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) + */ +address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + // TODO: Unimplemented generate_CRC32_updateBytes_entry + return 0; +} + +/** + * Method entry for intrinsic-candidate (non-native) methods: + * int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int end) + * Unlike CRC32, CRC32C does not have any methods marked as native + * CRC32C also uses an "end" variable instead of the length variable CRC32 uses + */ +address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + // TODO: Unimplemented generate_CRC32C_updateBytes_entry + return 0; +} + +void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // See more discussion in stackOverflow.hpp. + + const int shadow_zone_size = checked_cast(StackOverflow::stack_shadow_zone_size()); + const int page_size = os::vm_page_size(); + const int n_shadow_pages = shadow_zone_size / page_size; + +#ifdef ASSERT + Label L_good_limit; + __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); + __ bnez(t0, L_good_limit); + __ stop("shadow zone safe limit is not initialized"); + __ bind(L_good_limit); + + Label L_good_watermark; + __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); + __ bnez(t0, L_good_watermark); + __ stop("shadow zone growth watermark is not initialized"); + __ bind(L_good_watermark); +#endif + + Label L_done; + + __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); + __ bgtu(sp, t0, L_done); + + for (int p = 1; p <= n_shadow_pages; p++) { + __ bang_stack_with_offset(p * page_size); + } + + // Record the new watermark, but only if the update is above the safe limit. + // Otherwise, the next time around the check above would pass the safe limit. + __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); + __ bleu(sp, t0, L_done); + __ sd(sp, Address(xthread, JavaThread::shadow_zone_growth_watermark())); + + __ bind(L_done); +} + +// Interpreter stub for calling a native method. (asm interpreter) +// This sets up a somewhat different looking stack for calling the +// native method than the typical interpreter frame setup. +address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { + // determine code generation flags + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; + + // x11: Method* + // x30: sender sp + + address entry_point = __ pc(); + + const Address constMethod (xmethod, Method::const_offset()); + const Address access_flags (xmethod, Method::access_flags_offset()); + const Address size_of_parameters(x12, ConstMethod:: + size_of_parameters_offset()); + + // get parameter size (always needed) + __ ld(x12, constMethod); + __ load_unsigned_short(x12, size_of_parameters); + + // Native calls don't need the stack size check since they have no + // expression stack and the arguments are already on the stack and + // we only add a handful of words to the stack. + + // xmethod: Method* + // x12: size of parameters + // x30: sender sp + + // for natives the size of locals is zero + + // compute beginning of parameters (xlocals) + __ shadd(xlocals, x12, esp, xlocals, 3); + __ addi(xlocals, xlocals, -wordSize); + + // Pull SP back to minimum size: this avoids holes in the stack + __ andi(sp, esp, -16); + + // initialize fixed part of activation frame + generate_fixed_frame(true); + + // make sure method is native & not abstract +#ifdef ASSERT + __ lwu(x10, access_flags); + __ verify_access_flags(x10, JVM_ACC_NATIVE, "tried to execute non-native method as native", false); + __ verify_access_flags(x10, JVM_ACC_ABSTRACT, "tried to execute abstract method in interpreter"); +#endif + + // Since at this point in the method invocation the exception + // handler would try to exit the monitor of synchronized methods + // which hasn't been entered yet, we set the thread local variable + // _do_not_unlock_if_synchronized to true. The remove_activation + // will check this flag. + + const Address do_not_unlock_if_synchronized(xthread, + in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); + __ mv(t1, true); + __ sb(t1, do_not_unlock_if_synchronized); + + // increment invocation count & check for overflow + Label invocation_counter_overflow; + if (inc_counter) { + generate_counter_incr(&invocation_counter_overflow); + } + + Label continue_after_compile; + __ bind(continue_after_compile); + + bang_stack_shadow_pages(true); + + // reset the _do_not_unlock_if_synchronized flag + __ sb(zr, do_not_unlock_if_synchronized); + + // check for synchronized methods + // Must happen AFTER invocation_counter check and stack overflow check, + // so method is not locked if overflows. + if (synchronized) { + lock_method(); + } else { + // no synchronization necessary +#ifdef ASSERT + __ lwu(x10, access_flags); + __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method needs synchronization"); +#endif + } + + // start execution +#ifdef ASSERT + __ verify_frame_setup(); +#endif + + // jvmti support + __ notify_method_entry(); + + // work registers + const Register t = x18; + const Register result_handler = x19; + + // allocate space for parameters + __ ld(t, Address(xmethod, Method::const_offset())); + __ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset())); + + __ slli(t, t, Interpreter::logStackElementSize); + __ sub(x30, esp, t); + __ andi(sp, x30, -16); + __ mv(esp, x30); + + // get signature handler + { + Label L; + __ ld(t, Address(xmethod, Method::signature_handler_offset())); + __ bnez(t, L); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::prepare_native_call), + xmethod); + __ ld(t, Address(xmethod, Method::signature_handler_offset())); + __ bind(L); + } + + // call signature handler + assert(InterpreterRuntime::SignatureHandlerGenerator::from() == xlocals, + "adjust this code"); + assert(InterpreterRuntime::SignatureHandlerGenerator::to() == sp, + "adjust this code"); + assert(InterpreterRuntime::SignatureHandlerGenerator::temp() == t0, + "adjust this code"); + + // The generated handlers do not touch xmethod (the method). + // However, large signatures cannot be cached and are generated + // each time here. The slow-path generator can do a GC on return, + // so we must reload it after the call. + __ jalr(t); + __ get_method(xmethod); // slow path can do a GC, reload xmethod + + + // result handler is in x10 + // set result handler + __ mv(result_handler, x10); + // pass mirror handle if static call + { + Label L; + __ lwu(t, Address(xmethod, Method::access_flags_offset())); + __ andi(t0, t, JVM_ACC_STATIC); + __ beqz(t0, L); + // get mirror + __ load_mirror(t, xmethod); + // copy mirror into activation frame + __ sd(t, Address(fp, frame::interpreter_frame_oop_temp_offset * wordSize)); + // pass handle to mirror + __ addi(c_rarg1, fp, frame::interpreter_frame_oop_temp_offset * wordSize); + __ bind(L); + } + + // get native function entry point in x28 + { + Label L; + __ ld(x28, Address(xmethod, Method::native_function_offset())); + address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + __ mv(t1, unsatisfied); + __ ld(t1, t1); + __ bne(x28, t1, L); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::prepare_native_call), + xmethod); + __ get_method(xmethod); + __ ld(x28, Address(xmethod, Method::native_function_offset())); + __ bind(L); + } + + // pass JNIEnv + __ add(c_rarg0, xthread, in_bytes(JavaThread::jni_environment_offset())); + + // It is enough that the pc() points into the right code + // segment. It does not have to be the correct return pc. + Label native_return; + __ set_last_Java_frame(esp, fp, native_return, x30); + + // change thread state +#ifdef ASSERT + { + Label L; + __ lwu(t, Address(xthread, JavaThread::thread_state_offset())); + __ addi(t0, zr, (u1)_thread_in_Java); + __ beq(t, t0, L); + __ stop("Wrong thread state in native stub"); + __ bind(L); + } +#endif + + // Change state to native + __ la(t1, Address(xthread, JavaThread::thread_state_offset())); + __ mv(t0, _thread_in_native); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sw(t0, Address(t1)); + + // Call the native method. + __ jalr(x28); + __ bind(native_return); + __ get_method(xmethod); + // result potentially in x10 or f10 + + // make room for the pushes we're about to do + __ sub(t0, esp, 4 * wordSize); + __ andi(sp, t0, -16); + + // NOTE: The order of these pushes is known to frame::interpreter_frame_result + // in order to extract the result of a method call. If the order of these + // pushes change or anything else is added to the stack then the code in + // interpreter_frame_result must also change. + __ push(dtos); + __ push(ltos); + + // change thread state + // Force all preceding writes to be observed prior to thread state change + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + + __ mv(t0, _thread_in_native_trans); + __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + + // Force this write out before the read below + __ membar(MacroAssembler::AnyAny); + + // check for safepoint operation in progress and/or pending suspend requests + { + Label L, Continue; + + // We need an acquire here to ensure that any subsequent load of the + // global SafepointSynchronize::_state flag is ordered after this load + // of the thread-local polling word. We don't want this poll to + // return false (i.e. not safepointing) and a later poll of the global + // SafepointSynchronize::_state spuriously to return true. + // + // This is to avoid a race when we're in a native->Java transition + // racing the code which wakes up from a safepoint. + __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); + __ beqz(t1, Continue); + __ bind(L); + + // Don't use call_VM as it will see a possible pending exception + // and forward it and never return here preventing us from + // clearing _last_native_pc down below. So we do a runtime call by + // hand. + // + __ mv(c_rarg0, xthread); + __ mv(t1, CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ jalr(t1); + __ get_method(xmethod); + __ reinit_heapbase(); + __ bind(Continue); + } + + // change thread state + // Force all preceding writes to be observed prior to thread state change + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + + __ mv(t0, _thread_in_Java); + __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + + // reset_last_Java_frame + __ reset_last_Java_frame(true); + + if (CheckJNICalls) { + // clear_pending_jni_exception_check + __ sd(zr, Address(xthread, JavaThread::pending_jni_exception_check_fn_offset())); + } + + // reset handle block + __ ld(t, Address(xthread, JavaThread::active_handles_offset())); + __ sd(zr, Address(t, JNIHandleBlock::top_offset_in_bytes())); + + // If result is an oop unbox and store it in frame where gc will see it + // and result handler will pick it up + + { + Label no_oop; + __ la(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT))); + __ bne(t, result_handler, no_oop); + // Unbox oop result, e.g. JNIHandles::resolve result. + __ pop(ltos); + __ resolve_jobject(x10, xthread, t); + __ sd(x10, Address(fp, frame::interpreter_frame_oop_temp_offset * wordSize)); + // keep stack depth as expected by pushing oop which will eventually be discarded + __ push(ltos); + __ bind(no_oop); + } + + { + Label no_reguard; + __ lwu(t0, Address(xthread, in_bytes(JavaThread::stack_guard_state_offset()))); + __ addi(t1, zr, (u1)StackOverflow::stack_guard_yellow_reserved_disabled); + __ bne(t0, t1, no_reguard); + + __ pusha(); // only save smashed registers + __ mv(c_rarg0, xthread); + __ mv(t1, CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); + __ jalr(t1); + __ popa(); // only restore smashed registers + __ bind(no_reguard); + } + + // The method register is junk from after the thread_in_native transition + // until here. Also can't call_VM until the bcp has been + // restored. Need bcp for throwing exception below so get it now. + __ get_method(xmethod); + + // restore bcp to have legal interpreter frame, i.e., bci == 0 <=> + // xbcp == code_base() + __ ld(xbcp, Address(xmethod, Method::const_offset())); // get ConstMethod* + __ add(xbcp, xbcp, in_bytes(ConstMethod::codes_offset())); // get codebase + // handle exceptions (exception handling will handle unlocking!) + { + Label L; + __ ld(t0, Address(xthread, Thread::pending_exception_offset())); + __ beqz(t0, L); + // Note: At some point we may want to unify this with the code + // used in call_VM_base(); i.e., we should use the + // StubRoutines::forward_exception code. For now this doesn't work + // here because the sp is not correctly set at this point. + __ MacroAssembler::call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_pending_exception)); + __ should_not_reach_here(); + __ bind(L); + } + + // do unlocking if necessary + { + Label L; + __ lwu(t, Address(xmethod, Method::access_flags_offset())); + __ andi(t0, t, JVM_ACC_SYNCHRONIZED); + __ beqz(t0, L); + // the code below should be shared with interpreter macro + // assembler implementation + { + Label unlock; + // BasicObjectLock will be first in list, since this is a + // synchronized method. However, need to check that the object + // has not been unlocked by an explicit monitorexit bytecode. + + // monitor expect in c_rarg1 for slow unlock path + __ la(c_rarg1, Address(fp, // address of first monitor + (intptr_t)(frame::interpreter_frame_initial_sp_offset * + wordSize - sizeof(BasicObjectLock)))); + + __ ld(t, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); + __ bnez(t, unlock); + + // Entry already unlocked, need to throw exception + __ MacroAssembler::call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_illegal_monitor_state_exception)); + __ should_not_reach_here(); + + __ bind(unlock); + __ unlock_object(c_rarg1); + } + __ bind(L); + } + + // jvmti support + // Note: This must happen _after_ handling/throwing any exceptions since + // the exception handler code notifies the runtime of method exits + // too. If this happens before, method entry/exit notifications are + // not properly paired (was bug - gri 11/22/99). + __ notify_method_exit(vtos, InterpreterMacroAssembler::NotifyJVMTI); + + __ pop(ltos); + __ pop(dtos); + + __ jalr(result_handler); + + // remove activation + __ ld(esp, Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp + // remove frame anchor + __ leave(); + + // restore sender sp + __ mv(sp, esp); + + __ ret(); + + if (inc_counter) { + // Handle overflow of counter and compile method + __ bind(invocation_counter_overflow); + generate_counter_overflow(continue_after_compile); + } + + return entry_point; +} + +// +// Generic interpreted method entry to (asm) interpreter +// +address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { + + // determine code generation flags + const bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; + + // t0: sender sp + address entry_point = __ pc(); + + const Address constMethod(xmethod, Method::const_offset()); + const Address access_flags(xmethod, Method::access_flags_offset()); + const Address size_of_parameters(x13, + ConstMethod::size_of_parameters_offset()); + const Address size_of_locals(x13, ConstMethod::size_of_locals_offset()); + + // get parameter size (always needed) + // need to load the const method first + __ ld(x13, constMethod); + __ load_unsigned_short(x12, size_of_parameters); + + // x12: size of parameters + + __ load_unsigned_short(x13, size_of_locals); // get size of locals in words + __ sub(x13, x13, x12); // x13 = no. of additional locals + + // see if we've got enough room on the stack for locals plus overhead. + generate_stack_overflow_check(); + + // compute beginning of parameters (xlocals) + __ shadd(xlocals, x12, esp, t1, 3); + __ add(xlocals, xlocals, -wordSize); + + // Make room for additional locals + __ slli(t1, x13, 3); + __ sub(t0, esp, t1); + + // Padding between locals and fixed part of activation frame to ensure + // SP is always 16-byte aligned. + __ andi(sp, t0, -16); + + // x13 - # of additional locals + // allocate space for locals + // explicitly initialize locals + { + Label exit, loop; + __ blez(x13, exit); // do nothing if x13 <= 0 + __ bind(loop); + __ sd(zr, Address(t0)); + __ add(t0, t0, wordSize); + __ add(x13, x13, -1); // until everything initialized + __ bnez(x13, loop); + __ bind(exit); + } + + // And the base dispatch table + __ get_dispatch(); + + // initialize fixed part of activation frame + generate_fixed_frame(false); + + // make sure method is not native & not abstract +#ifdef ASSERT + __ lwu(x10, access_flags); + __ verify_access_flags(x10, JVM_ACC_NATIVE, "tried to execute native method as non-native"); + __ verify_access_flags(x10, JVM_ACC_ABSTRACT, "tried to execute abstract method in interpreter"); +#endif + + // Since at this point in the method invocation the exception + // handler would try to exit the monitor of synchronized methods + // which hasn't been entered yet, we set the thread local variable + // _do_not_unlock_if_synchronized to true. The remove_activation + // will check this flag. + + const Address do_not_unlock_if_synchronized(xthread, + in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); + __ mv(t1, true); + __ sb(t1, do_not_unlock_if_synchronized); + + Label no_mdp; + const Register mdp = x13; + __ ld(mdp, Address(xmethod, Method::method_data_offset())); + __ beqz(mdp, no_mdp); + __ add(mdp, mdp, in_bytes(MethodData::data_offset())); + __ profile_parameters_type(mdp, x11, x12, x14); // use x11, x12, x14 as tmp registers + __ bind(no_mdp); + + // increment invocation count & check for overflow + Label invocation_counter_overflow; + if (inc_counter) { + generate_counter_incr(&invocation_counter_overflow); + } + + Label continue_after_compile; + __ bind(continue_after_compile); + + bang_stack_shadow_pages(false); + + // reset the _do_not_unlock_if_synchronized flag + __ sb(zr, do_not_unlock_if_synchronized); + + // check for synchronized methods + // Must happen AFTER invocation_counter check and stack overflow check, + // so method is not locked if overflows. + if (synchronized) { + // Allocate monitor and lock method + lock_method(); + } else { + // no synchronization necessary +#ifdef ASSERT + __ lwu(x10, access_flags); + __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method needs synchronization"); +#endif + } + + // start execution +#ifdef ASSERT + __ verify_frame_setup(); +#endif + + // jvmti support + __ notify_method_entry(); + + __ dispatch_next(vtos); + + // invocation counter overflow + if (inc_counter) { + // Handle overflow of counter and compile method + __ bind(invocation_counter_overflow); + generate_counter_overflow(continue_after_compile); + } + + return entry_point; +} + +//----------------------------------------------------------------------------- +// Exceptions + +void TemplateInterpreterGenerator::generate_throw_exception() { + // Entry point in previous activation (i.e., if the caller was + // interpreted) + Interpreter::_rethrow_exception_entry = __ pc(); + // Restore sp to interpreter_frame_last_sp even though we are going + // to empty the expression stack for the exception processing. + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + // x10: exception + // x13: return address/pc that threw exception + __ restore_bcp(); // xbcp points to call/send + __ restore_locals(); + __ restore_constant_pool_cache(); + __ reinit_heapbase(); // restore xheapbase as heapbase. + __ get_dispatch(); + + // Entry point for exceptions thrown within interpreter code + Interpreter::_throw_exception_entry = __ pc(); + // If we came here via a NullPointerException on the receiver of a + // method, xthread may be corrupt. + __ get_method(xmethod); + // expression stack is undefined here + // x10: exception + // xbcp: exception bcp + __ verify_oop(x10); + __ mv(c_rarg1, x10); + + // expression stack must be empty before entering the VM in case of + // an exception + __ empty_expression_stack(); + // find exception handler address and preserve exception oop + __ call_VM(x13, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::exception_handler_for_exception), + c_rarg1); + + // Calculate stack limit + __ ld(t0, Address(xmethod, Method::const_offset())); + __ lhu(t0, Address(t0, ConstMethod::max_stack_offset())); + __ add(t0, t0, frame::interpreter_frame_monitor_size() + 4); + __ ld(t1, Address(fp, frame::interpreter_frame_initial_sp_offset * wordSize)); + __ slli(t0, t0, 3); + __ sub(t0, t1, t0); + __ andi(sp, t0, -16); + + // x10: exception handler entry point + // x13: preserved exception oop + // xbcp: bcp for exception handler + __ push_ptr(x13); // push exception which is now the only value on the stack + __ jr(x10); // jump to exception handler (may be _remove_activation_entry!) + + // If the exception is not handled in the current frame the frame is + // removed and the exception is rethrown (i.e. exception + // continuation is _rethrow_exception). + // + // Note: At this point the bci is still the bxi for the instruction + // which caused the exception and the expression stack is + // empty. Thus, for any VM calls at this point, GC will find a legal + // oop map (with empty expression stack). + + // + // JVMTI PopFrame support + // + + Interpreter::_remove_activation_preserving_args_entry = __ pc(); + __ empty_expression_stack(); + // Set the popframe_processing bit in pending_popframe_condition + // indicating that we are currently handling popframe, so that + // call_VMs that may happen later do not trigger new popframe + // handling cycles. + __ lwu(x13, Address(xthread, JavaThread::popframe_condition_offset())); + __ ori(x13, x13, JavaThread::popframe_processing_bit); + __ sw(x13, Address(xthread, JavaThread::popframe_condition_offset())); + + { + // Check to see whether we are returning to a deoptimized frame. + // (The PopFrame call ensures that the caller of the popped frame is + // either interpreted or compiled and deoptimizes it if compiled.) + // In this case, we can't call dispatch_next() after the frame is + // popped, but instead must save the incoming arguments and restore + // them after deoptimization has occurred. + // + // Note that we don't compare the return PC against the + // deoptimization blob's unpack entry because of the presence of + // adapter frames in C2. + Label caller_not_deoptimized; + __ ld(c_rarg1, Address(fp, frame::return_addr_offset * wordSize)); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::interpreter_contains), c_rarg1); + __ bnez(x10, caller_not_deoptimized); + + // Compute size of arguments for saving when returning to + // deoptimized caller + __ get_method(x10); + __ ld(x10, Address(x10, Method::const_offset())); + __ load_unsigned_short(x10, Address(x10, in_bytes(ConstMethod:: + size_of_parameters_offset()))); + __ slli(x10, x10, Interpreter::logStackElementSize); + __ restore_locals(); + __ sub(xlocals, xlocals, x10); + __ add(xlocals, xlocals, wordSize); + // Save these arguments + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, + Deoptimization:: + popframe_preserve_args), + xthread, x10, xlocals); + + __ remove_activation(vtos, + /* throw_monitor_exception */ false, + /* install_monitor_exception */ false, + /* notify_jvmdi */ false); + + // Inform deoptimization that it is responsible for restoring + // these arguments + __ mv(t0, JavaThread::popframe_force_deopt_reexecution_bit); + __ sw(t0, Address(xthread, JavaThread::popframe_condition_offset())); + + // Continue in deoptimization handler + __ ret(); + + __ bind(caller_not_deoptimized); + } + + __ remove_activation(vtos, + /* throw_monitor_exception */ false, + /* install_monitor_exception */ false, + /* notify_jvmdi */ false); + + // Restore the last_sp and null it out + __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + + __ restore_bcp(); + __ restore_locals(); + __ restore_constant_pool_cache(); + __ get_method(xmethod); + __ get_dispatch(); + + // The method data pointer was incremented already during + // call profiling. We have to restore the mdp for the current bcp. + if (ProfileInterpreter) { + __ set_method_data_pointer_for_bcp(); + } + + // Clear the popframe condition flag + __ sw(zr, Address(xthread, JavaThread::popframe_condition_offset())); + assert(JavaThread::popframe_inactive == 0, "fix popframe_inactive"); + +#if INCLUDE_JVMTI + { + Label L_done; + + __ lbu(t0, Address(xbcp, 0)); + __ li(t1, Bytecodes::_invokestatic); + __ bne(t1, t0, L_done); + + // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. + // Detect such a case in the InterpreterRuntime function and return the member name argument,or NULL. + + __ ld(c_rarg0, Address(xlocals, 0)); + __ call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null),c_rarg0, xmethod, xbcp); + + __ beqz(x10, L_done); + + __ sd(x10, Address(esp, 0)); + __ bind(L_done); + } +#endif // INCLUDE_JVMTI + + // Restore machine SP + __ ld(t0, Address(xmethod, Method::const_offset())); + __ lhu(t0, Address(t0, ConstMethod::max_stack_offset())); + __ add(t0, t0, frame::interpreter_frame_monitor_size() + 4); + __ ld(t1, Address(fp, frame::interpreter_frame_initial_sp_offset * wordSize)); + __ slliw(t0, t0, 3); + __ sub(t0, t1, t0); + __ andi(sp, t0, -16); + + __ dispatch_next(vtos); + // end of PopFrame support + + Interpreter::_remove_activation_entry = __ pc(); + + // preserve exception over this code sequence + __ pop_ptr(x10); + __ sd(x10, Address(xthread, JavaThread::vm_result_offset())); + // remove the activation (without doing throws on illegalMonitorExceptions) + __ remove_activation(vtos, false, true, false); + // restore exception + __ get_vm_result(x10, xthread); + + // In between activations - previous activation type unknown yet + // compute continuation point - the continuation point expects the + // following registers set up: + // + // x10: exception + // ra: return address/pc that threw exception + // sp: expression stack of caller + // fp: fp of caller + // FIXME: There's no point saving ra here because VM calls don't trash it + __ sub(sp, sp, 2 * wordSize); + __ sd(x10, Address(sp, 0)); // save exception + __ sd(ra, Address(sp, wordSize)); // save return address + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, + SharedRuntime::exception_handler_for_return_address), + xthread, ra); + __ mv(x11, x10); // save exception handler + __ ld(x10, Address(sp, 0)); // restore exception + __ ld(ra, Address(sp, wordSize)); // restore return address + __ add(sp, sp, 2 * wordSize); + // We might be returning to a deopt handler that expects x13 to + // contain the exception pc + __ mv(x13, ra); + // Note that an "issuing PC" is actually the next PC after the call + __ jr(x11); // jump to exception + // handler of caller +} + +// +// JVMTI ForceEarlyReturn support +// +address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) { + address entry = __ pc(); + + __ restore_bcp(); + __ restore_locals(); + __ empty_expression_stack(); + __ load_earlyret_value(state); + + __ ld(t0, Address(xthread, JavaThread::jvmti_thread_state_offset())); + Address cond_addr(t0, JvmtiThreadState::earlyret_state_offset()); + + // Clear the earlyret state + assert(JvmtiThreadState::earlyret_inactive == 0, "should be"); + __ sd(zr, cond_addr); + + __ remove_activation(state, + false, /* throw_monitor_exception */ + false, /* install_monitor_exception */ + true); /* notify_jvmdi */ + __ ret(); + + return entry; +} +// end of ForceEarlyReturn support + +//----------------------------------------------------------------------------- +// Helper for vtos entry point generation + +void TemplateInterpreterGenerator::set_vtos_entry_points(Template* t, + address& bep, + address& cep, + address& sep, + address& aep, + address& iep, + address& lep, + address& fep, + address& dep, + address& vep) { + assert(t != NULL && t->is_valid() && t->tos_in() == vtos, "illegal template"); + Label L; + aep = __ pc(); __ push_ptr(); __ j(L); + fep = __ pc(); __ push_f(); __ j(L); + dep = __ pc(); __ push_d(); __ j(L); + lep = __ pc(); __ push_l(); __ j(L); + bep = cep = sep = + iep = __ pc(); __ push_i(); + vep = __ pc(); + __ bind(L); + generate_and_dispatch(t); +} + +//----------------------------------------------------------------------------- + +// Non-product code +#ifndef PRODUCT +address TemplateInterpreterGenerator::generate_trace_code(TosState state) { + address entry = __ pc(); + + __ push_reg(ra); + __ push(state); + __ push_reg(RegSet::range(x10, x17) + RegSet::range(x5, x7) + RegSet::range(x28, x31), sp); + __ mv(c_rarg2, x10); // Pass itos + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), c_rarg1, c_rarg2, c_rarg3); + __ pop_reg(RegSet::range(x10, x17) + RegSet::range(x5, x7) + RegSet::range(x28, x31), sp); + __ pop(state); + __ pop_reg(ra); + __ ret(); // return from result handler + + return entry; +} + +void TemplateInterpreterGenerator::count_bytecode() { + __ push_reg(t0); + __ push_reg(x10); + __ mv(x10, (address) &BytecodeCounter::_counter_value); + __ li(t0, 1); + __ amoadd_d(zr, x10, t0, Assembler::aqrl); + __ pop_reg(x10); + __ pop_reg(t0); +} + +void TemplateInterpreterGenerator::histogram_bytecode(Template* t) { ; } + +void TemplateInterpreterGenerator::histogram_bytecode_pair(Template* t) { ; } + +void TemplateInterpreterGenerator::trace_bytecode(Template* t) { + // Call a little run-time stub to avoid blow-up for each bytecode. + // The run-time runtime saves the right registers, depending on + // the tosca in-state for the given template. + + assert(Interpreter::trace_code(t->tos_in()) != NULL, "entry must have been generated"); + __ jal(Interpreter::trace_code(t->tos_in())); + __ reinit_heapbase(); +} + +void TemplateInterpreterGenerator::stop_interpreter_at() { + Label L; + __ push_reg(t0); + __ mv(t0, (address) &BytecodeCounter::_counter_value); + __ ld(t0, Address(t0)); + __ mv(t1, StopInterpreterAt); + __ bne(t0, t1, L); + __ ebreak(); + __ bind(L); + __ pop_reg(t0); +} + +#endif // !PRODUCT diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2a301c6e740cffe7257fbb97ae375894c829986 --- /dev/null +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -0,0 +1,3951 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "gc/shared/tlab_globals.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/templateTable.hpp" +#include "memory/universe.hpp" +#include "oops/method.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" +#include "utilities/powerOfTwo.hpp" + +#define __ _masm-> + +// Address computation: local variables + +static inline Address iaddress(int n) { + return Address(xlocals, Interpreter::local_offset_in_bytes(n)); +} + +static inline Address laddress(int n) { + return iaddress(n + 1); +} + +static inline Address faddress(int n) { + return iaddress(n); +} + +static inline Address daddress(int n) { + return laddress(n); +} + +static inline Address aaddress(int n) { + return iaddress(n); +} + +static inline Address iaddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + assert_cond(_masm != NULL); + _masm->shadd(temp, r, xlocals, temp, 3); + return Address(temp, 0); +} + +static inline Address laddress(Register r, Register temp, + InterpreterMacroAssembler* _masm) { + assert_cond(_masm != NULL); + _masm->shadd(temp, r, xlocals, temp, 3); + return Address(temp, Interpreter::local_offset_in_bytes(1));; +} + +static inline Address faddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + return iaddress(r, temp, _masm); +} + +static inline Address daddress(Register r, Register temp, + InterpreterMacroAssembler* _masm) { + return laddress(r, temp, _masm); +} + +static inline Address aaddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + return iaddress(r, temp, _masm); +} + +static inline Address at_rsp() { + return Address(esp, 0); +} + +// At top of Java expression stack which may be different than esp(). It +// isn't for category 1 objects. +static inline Address at_tos () { + return Address(esp, Interpreter::expr_offset_in_bytes(0)); +} + +static inline Address at_tos_p1() { + return Address(esp, Interpreter::expr_offset_in_bytes(1)); +} + +static inline Address at_tos_p2() { + return Address(esp, Interpreter::expr_offset_in_bytes(2)); +} + +static inline Address at_tos_p3() { + return Address(esp, Interpreter::expr_offset_in_bytes(3)); +} + +static inline Address at_tos_p4() { + return Address(esp, Interpreter::expr_offset_in_bytes(4)); +} + +static inline Address at_tos_p5() { + return Address(esp, Interpreter::expr_offset_in_bytes(5)); +} + +// Miscelaneous helper routines +// Store an oop (or NULL) at the Address described by obj. +// If val == noreg this means store a NULL +static void do_oop_store(InterpreterMacroAssembler* _masm, + Address dst, + Register val, + DecoratorSet decorators) { + assert(val == noreg || val == x10, "parameter is just for looks"); + assert_cond(_masm != NULL); + __ store_heap_oop(dst, val, x29, x11, decorators); +} + +static void do_oop_load(InterpreterMacroAssembler* _masm, + Address src, + Register dst, + DecoratorSet decorators) { + assert_cond(_masm != NULL); + __ load_heap_oop(dst, src, x7, x11, decorators); +} + +Address TemplateTable::at_bcp(int offset) { + assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); + return Address(xbcp, offset); +} + +void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, + Register temp_reg, bool load_bc_into_bc_reg/*=true*/, + int byte_no) +{ + if (!RewriteBytecodes) { return; } + Label L_patch_done; + + switch (bc) { + case Bytecodes::_fast_aputfield: // fall through + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_dputfield: // fall through + case Bytecodes::_fast_fputfield: // fall through + case Bytecodes::_fast_iputfield: // fall through + case Bytecodes::_fast_lputfield: // fall through + case Bytecodes::_fast_sputfield: { + // We skip bytecode quickening for putfield instructions when + // the put_code written to the constant pool cache is zero. + // This is required so that every execution of this instruction + // calls out to InterpreterRuntime::resolve_get_put to do + // additional, required work. + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + assert(load_bc_into_bc_reg, "we use bc_reg as temp"); + __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1); + __ mv(bc_reg, bc); + __ beqz(temp_reg, L_patch_done); + break; + } + default: + assert(byte_no == -1, "sanity"); + // the pair bytecodes have already done the load. + if (load_bc_into_bc_reg) { + __ mv(bc_reg, bc); + } + } + + if (JvmtiExport::can_post_breakpoint()) { + Label L_fast_patch; + // if a breakpoint is present we can't rewrite the stream directly + __ load_unsigned_byte(temp_reg, at_bcp(0)); + __ addi(temp_reg, temp_reg, -Bytecodes::_breakpoint); // temp_reg is temporary register. + __ bnez(temp_reg, L_fast_patch); + // Let breakpoint table handling rewrite to quicker bytecode + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), xmethod, xbcp, bc_reg); + __ j(L_patch_done); + __ bind(L_fast_patch); + } + +#ifdef ASSERT + Label L_okay; + __ load_unsigned_byte(temp_reg, at_bcp(0)); + __ beq(temp_reg, bc_reg, L_okay); + __ addi(temp_reg, temp_reg, -(int) Bytecodes::java_code(bc)); + __ beqz(temp_reg, L_okay); + __ stop("patching the wrong bytecode"); + __ bind(L_okay); +#endif + + // patch bytecode + __ sb(bc_reg, at_bcp(0)); + __ bind(L_patch_done); +} + +// Individual instructions + +void TemplateTable::nop() { + transition(vtos, vtos); + // nothing to do +} + +void TemplateTable::shouldnotreachhere() { + transition(vtos, vtos); + __ stop("should not reach here bytecode"); +} + +void TemplateTable::aconst_null() +{ + transition(vtos, atos); + __ mv(x10, zr); +} + +void TemplateTable::iconst(int value) +{ + transition(vtos, itos); + __ li(x10, value); +} + +void TemplateTable::lconst(int value) +{ + transition(vtos, ltos); + __ li(x10, value); +} + +void TemplateTable::fconst(int value) +{ + transition(vtos, ftos); + static float fBuf[2] = {1.0, 2.0}; + __ mv(t0, (intptr_t)fBuf); + switch (value) { + case 0: + __ fmv_w_x(f10, zr); + break; + case 1: + __ flw(f10, t0, 0); + break; + case 2: + __ flw(f10, t0, sizeof(float)); + break; + default: + ShouldNotReachHere(); + } +} + +void TemplateTable::dconst(int value) +{ + transition(vtos, dtos); + static double dBuf[2] = {1.0, 2.0}; + __ mv(t0, (intptr_t)dBuf); + switch (value) { + case 0: + __ fmv_d_x(f10, zr); + break; + case 1: + __ fld(f10, t0, 0); + break; + case 2: + __ fld(f10, t0, sizeof(double)); + break; + default: + ShouldNotReachHere(); + } +} + +void TemplateTable::bipush() +{ + transition(vtos, itos); + __ load_signed_byte(x10, at_bcp(1)); +} + +void TemplateTable::sipush() +{ + transition(vtos, itos); + __ load_unsigned_short(x10, at_bcp(1)); + __ revb_w_w(x10, x10); + __ sraiw(x10, x10, 16); +} + +void TemplateTable::ldc(bool wide) +{ + transition(vtos, vtos); + Label call_ldc, notFloat, notClass, notInt, Done; + + if (wide) { + __ get_unsigned_2_byte_index_at_bcp(x11, 1); + } else { + __ load_unsigned_byte(x11, at_bcp(1)); + } + __ get_cpool_and_tags(x12, x10); + + const int base_offset = ConstantPool::header_size() * wordSize; + const int tags_offset = Array::base_offset_in_bytes(); + + // get type + __ addi(x13, x11, tags_offset); + __ add(x13, x10, x13); + __ membar(MacroAssembler::AnyAny); + __ lbu(x13, Address(x13, 0)); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + + // unresolved class - get the resolved class + __ mv(t1, (u1)JVM_CONSTANT_UnresolvedClass); + __ beq(x13, t1, call_ldc); + + // unresolved class in error state - call into runtime to throw the error + // from the first resolution attempt + __ mv(t1, (u1)JVM_CONSTANT_UnresolvedClassInError); + __ beq(x13, t1, call_ldc); + + // resolved class - need to call vm to get java mirror of the class + __ mv(t1, (u1)JVM_CONSTANT_Class); + __ bne(x13, t1, notClass); + + __ bind(call_ldc); + __ mv(c_rarg1, wide); + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), c_rarg1); + __ push_ptr(x10); + __ verify_oop(x10); + __ j(Done); + + __ bind(notClass); + __ mv(t1, (u1)JVM_CONSTANT_Float); + __ bne(x13, t1, notFloat); + + // ftos + __ shadd(x11, x11, x12, x11, 3); + __ flw(f10, Address(x11, base_offset)); + __ push_f(f10); + __ j(Done); + + __ bind(notFloat); + + __ mv(t1, (u1)JVM_CONSTANT_Integer); + __ bne(x13, t1, notInt); + + // itos + __ shadd(x11, x11, x12, x11, 3); + __ lw(x10, Address(x11, base_offset)); + __ push_i(x10); + __ j(Done); + + __ bind(notInt); + condy_helper(Done); + + __ bind(Done); +} + +// Fast path for caching oop constants. +void TemplateTable::fast_aldc(bool wide) +{ + transition(vtos, atos); + + const Register result = x10; + const Register tmp = x11; + const Register rarg = x12; + + const int index_size = wide ? sizeof(u2) : sizeof(u1); + + Label resolved; + + // We are resolved if the resolved reference cache entry contains a + // non-null object (String, MethodType, etc.) + assert_different_registers(result, tmp); + __ get_cache_index_at_bcp(tmp, 1, index_size); + __ load_resolved_reference_at_index(result, tmp); + __ bnez(result, resolved); + + const address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); + + // first time invocation - must resolve first + __ mv(rarg, (int)bytecode()); + __ call_VM(result, entry, rarg); + + __ bind(resolved); + + { // Check for the null sentinel. + // If we just called the VM, it already did the mapping for us, + // but it's harmless to retry. + Label notNull; + + // Stash null_sentinel address to get its value later + int32_t offset = 0; + __ movptr_with_offset(rarg, Universe::the_null_sentinel_addr(), offset); + __ ld(tmp, Address(rarg, offset)); + __ resolve_oop_handle(tmp); + __ bne(result, tmp, notNull); + __ mv(result, zr); // NULL object reference + __ bind(notNull); + } + + if (VerifyOops) { + // Safe to call with 0 result + __ verify_oop(result); + } +} + +void TemplateTable::ldc2_w() +{ + transition(vtos, vtos); + Label notDouble, notLong, Done; + __ get_unsigned_2_byte_index_at_bcp(x10, 1); + + __ get_cpool_and_tags(x11, x12); + const int base_offset = ConstantPool::header_size() * wordSize; + const int tags_offset = Array::base_offset_in_bytes(); + + // get type + __ add(x12, x12, x10); + __ load_unsigned_byte(x12, Address(x12, tags_offset)); + __ mv(t1, JVM_CONSTANT_Double); + __ bne(x12, t1, notDouble); + + // dtos + __ shadd(x12, x10, x11, x12, 3); + __ fld(f10, Address(x12, base_offset)); + __ push_d(f10); + __ j(Done); + + __ bind(notDouble); + __ mv(t1, (int)JVM_CONSTANT_Long); + __ bne(x12, t1, notLong); + + // ltos + __ shadd(x10, x10, x11, x10, 3); + __ ld(x10, Address(x10, base_offset)); + __ push_l(x10); + __ j(Done); + + __ bind(notLong); + condy_helper(Done); + __ bind(Done); +} + +void TemplateTable::condy_helper(Label& Done) +{ + const Register obj = x10; + const Register rarg = x11; + const Register flags = x12; + const Register off = x13; + + const address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); + + __ mv(rarg, (int) bytecode()); + __ call_VM(obj, entry, rarg); + + __ get_vm_result_2(flags, xthread); + + // VMr = obj = base address to find primitive value to push + // VMr2 = flags = (tos, off) using format of CPCE::_flags + __ mv(off, flags); + __ mv(t0, ConstantPoolCacheEntry::field_index_mask); + __ andrw(off, off, t0); + + __ add(off, obj, off); + const Address field(off, 0); // base + R---->base + offset + + __ slli(flags, flags, XLEN - (ConstantPoolCacheEntry::tos_state_shift + ConstantPoolCacheEntry::tos_state_bits)); + __ srli(flags, flags, XLEN - ConstantPoolCacheEntry::tos_state_bits); // (1 << 5) - 4 --> 28~31==> flags:0~3 + + switch (bytecode()) { + case Bytecodes::_ldc: // fall through + case Bytecodes::_ldc_w: { + // tos in (itos, ftos, stos, btos, ctos, ztos) + Label notInt, notFloat, notShort, notByte, notChar, notBool; + __ mv(t1, itos); + __ bne(flags, t1, notInt); + // itos + __ lw(x10, field); + __ push(itos); + __ j(Done); + + __ bind(notInt); + __ mv(t1, ftos); + __ bne(flags, t1, notFloat); + // ftos + __ load_float(field); + __ push(ftos); + __ j(Done); + + __ bind(notFloat); + __ mv(t1, stos); + __ bne(flags, t1, notShort); + // stos + __ load_signed_short(x10, field); + __ push(stos); + __ j(Done); + + __ bind(notShort); + __ mv(t1, btos); + __ bne(flags, t1, notByte); + // btos + __ load_signed_byte(x10, field); + __ push(btos); + __ j(Done); + + __ bind(notByte); + __ mv(t1, ctos); + __ bne(flags, t1, notChar); + // ctos + __ load_unsigned_short(x10, field); + __ push(ctos); + __ j(Done); + + __ bind(notChar); + __ mv(t1, ztos); + __ bne(flags, t1, notBool); + // ztos + __ load_signed_byte(x10, field); + __ push(ztos); + __ j(Done); + + __ bind(notBool); + break; + } + + case Bytecodes::_ldc2_w: { + Label notLong, notDouble; + __ mv(t1, ltos); + __ bne(flags, t1, notLong); + // ltos + __ ld(x10, field); + __ push(ltos); + __ j(Done); + + __ bind(notLong); + __ mv(t1, dtos); + __ bne(flags, t1, notDouble); + // dtos + __ load_double(field); + __ push(dtos); + __ j(Done); + + __ bind(notDouble); + break; + } + + default: + ShouldNotReachHere(); + } + + __ stop("bad ldc/condy"); +} + +void TemplateTable::locals_index(Register reg, int offset) +{ + __ lbu(reg, at_bcp(offset)); + __ neg(reg, reg); +} + +void TemplateTable::iload() { + iload_internal(); +} + +void TemplateTable::nofast_iload() { + iload_internal(may_not_rewrite); +} + +void TemplateTable::iload_internal(RewriteControl rc) { + transition(vtos, itos); + if (RewriteFrequentPairs && rc == may_rewrite) { + Label rewrite, done; + const Register bc = x14; + + // get next bytecode + __ load_unsigned_byte(x11, at_bcp(Bytecodes::length_for(Bytecodes::_iload))); + + // if _iload, wait to rewrite to iload2. We only want to rewrite the + // last two iloads in a pair. Comparing against fast_iload means that + // the next bytecode is neither an iload or a caload, and therefore + // an iload pair. + __ mv(t1, Bytecodes::_iload); + __ beq(x11, t1, done); + + // if _fast_iload rewrite to _fast_iload2 + __ mv(t1, Bytecodes::_fast_iload); + __ mv(bc, Bytecodes::_fast_iload2); + __ beq(x11, t1, rewrite); + + // if _caload rewrite to _fast_icaload + __ mv(t1, Bytecodes::_caload); + __ mv(bc, Bytecodes::_fast_icaload); + __ beq(x11, t1, rewrite); + + // else rewrite to _fast_iload + __ mv(bc, Bytecodes::_fast_iload); + + // rewrite + // bc: new bytecode + __ bind(rewrite); + patch_bytecode(Bytecodes::_iload, bc, x11, false); + __ bind(done); + + } + + // do iload, get the local value into tos + locals_index(x11); + __ lw(x10, iaddress(x11, x10, _masm)); +} + +void TemplateTable::fast_iload2() +{ + transition(vtos, itos); + locals_index(x11); + __ lw(x10, iaddress(x11, x10, _masm)); + __ push(itos); + locals_index(x11, 3); + __ lw(x10, iaddress(x11, x10, _masm)); +} + +void TemplateTable::fast_iload() +{ + transition(vtos, itos); + locals_index(x11); + __ lw(x10, iaddress(x11, x10, _masm)); +} + +void TemplateTable::lload() +{ + transition(vtos, ltos); + __ lbu(x11, at_bcp(1)); + __ slli(x11, x11, LogBytesPerWord); + __ sub(x11, xlocals, x11); + __ ld(x10, Address(x11, Interpreter::local_offset_in_bytes(1))); +} + +void TemplateTable::fload() +{ + transition(vtos, ftos); + locals_index(x11); + __ flw(f10, faddress(x11, t0, _masm)); +} + +void TemplateTable::dload() +{ + transition(vtos, dtos); + __ lbu(x11, at_bcp(1)); + __ slli(x11, x11, LogBytesPerWord); + __ sub(x11, xlocals, x11); + __ fld(f10, Address(x11, Interpreter::local_offset_in_bytes(1))); +} + +void TemplateTable::aload() +{ + transition(vtos, atos); + locals_index(x11); + __ ld(x10, iaddress(x11, x10, _masm)); + +} + +void TemplateTable::locals_index_wide(Register reg) { + __ lhu(reg, at_bcp(2)); + __ revb_h_h_u(reg, reg); // reverse bytes in half-word and zero-extend + __ neg(reg, reg); +} + +void TemplateTable::wide_iload() { + transition(vtos, itos); + locals_index_wide(x11); + __ lw(x10, iaddress(x11, t0, _masm)); +} + +void TemplateTable::wide_lload() +{ + transition(vtos, ltos); + __ lhu(x11, at_bcp(2)); + __ revb_h_h_u(x11, x11); // reverse bytes in half-word and zero-extend + __ slli(x11, x11, LogBytesPerWord); + __ sub(x11, xlocals, x11); + __ ld(x10, Address(x11, Interpreter::local_offset_in_bytes(1))); +} + +void TemplateTable::wide_fload() +{ + transition(vtos, ftos); + locals_index_wide(x11); + __ flw(f10, faddress(x11, t0, _masm)); +} + +void TemplateTable::wide_dload() +{ + transition(vtos, dtos); + __ lhu(x11, at_bcp(2)); + __ revb_h_h_u(x11, x11); // reverse bytes in half-word and zero-extend + __ slli(x11, x11, LogBytesPerWord); + __ sub(x11, xlocals, x11); + __ fld(f10, Address(x11, Interpreter::local_offset_in_bytes(1))); +} + +void TemplateTable::wide_aload() +{ + transition(vtos, atos); + locals_index_wide(x11); + __ ld(x10, aaddress(x11, t0, _masm)); +} + +void TemplateTable::index_check(Register array, Register index) +{ + // destroys x11, t0 + // check array + __ null_check(array, arrayOopDesc::length_offset_in_bytes()); + // sign extend index for use by indexed load + // check index + const Register length = t0; + __ lwu(length, Address(array, arrayOopDesc::length_offset_in_bytes())); + if (index != x11) { + assert(x11 != array, "different registers"); + __ mv(x11, index); + } + Label ok; + __ addw(index, index, zr); + __ bltu(index, length, ok); + __ mv(x13, array); + __ mv(t0, Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); + __ jr(t0); + __ bind(ok); +} + +void TemplateTable::iaload() +{ + transition(itos, itos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_INT) >> 2); + __ shadd(x10, x11, x10, t0, 2); + __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); + __ addw(x10, x10, zr); // signed extended +} + +void TemplateTable::laload() +{ + transition(itos, ltos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_LONG) >> 3); + __ shadd(x10, x11, x10, t0, 3); + __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::faload() +{ + transition(itos, ftos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_FLOAT) >> 2); + __ shadd(x10, x11, x10, t0, 2); + __ access_load_at(T_FLOAT, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::daload() +{ + transition(itos, dtos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) >> 3); + __ shadd(x10, x11, x10, t0, 3); + __ access_load_at(T_DOUBLE, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::aaload() +{ + transition(itos, atos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_OBJECT) >> LogBytesPerHeapOop); + __ shadd(x10, x11, x10, t0, LogBytesPerHeapOop); + do_oop_load(_masm, + Address(x10), + x10, + IS_ARRAY); +} + +void TemplateTable::baload() +{ + transition(itos, itos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_BYTE) >> 0); + __ shadd(x10, x11, x10, t0, 0); + __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::caload() +{ + transition(itos, itos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1); + __ shadd(x10, x11, x10, t0, 1); + __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +// iload followed by caload frequent pair +void TemplateTable::fast_icaload() +{ + transition(vtos, itos); + // load index out of locals + locals_index(x12); + __ lw(x11, iaddress(x12, x11, _masm)); + __ pop_ptr(x10); + + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11, kills t0 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1); // addi, max imm is 2^11 + __ shadd(x10, x11, x10, t0, 1); + __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::saload() +{ + transition(itos, itos); + __ mv(x11, x10); + __ pop_ptr(x10); + // x10: array + // x11: index + index_check(x10, x11); // leaves index in x11, kills t0 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_SHORT) >> 1); + __ shadd(x10, x11, x10, t0, 1); + __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, x10, Address(x10), noreg, noreg); +} + +void TemplateTable::iload(int n) +{ + transition(vtos, itos); + __ lw(x10, iaddress(n)); +} + +void TemplateTable::lload(int n) +{ + transition(vtos, ltos); + __ ld(x10, laddress(n)); +} + +void TemplateTable::fload(int n) +{ + transition(vtos, ftos); + __ flw(f10, faddress(n)); +} + +void TemplateTable::dload(int n) +{ + transition(vtos, dtos); + __ fld(f10, daddress(n)); +} + +void TemplateTable::aload(int n) +{ + transition(vtos, atos); + __ ld(x10, iaddress(n)); +} + +void TemplateTable::aload_0() { + aload_0_internal(); +} + +void TemplateTable::nofast_aload_0() { + aload_0_internal(may_not_rewrite); +} + +void TemplateTable::aload_0_internal(RewriteControl rc) { + // According to bytecode histograms, the pairs: + // + // _aload_0, _fast_igetfield + // _aload_0, _fast_agetfield + // _aload_0, _fast_fgetfield + // + // occur frequently. If RewriteFrequentPairs is set, the (slow) + // _aload_0 bytecode checks if the next bytecode is either + // _fast_igetfield, _fast_agetfield or _fast_fgetfield and then + // rewrites the current bytecode into a pair bytecode; otherwise it + // rewrites the current bytecode into _fast_aload_0 that doesn't do + // the pair check anymore. + // + // Note: If the next bytecode is _getfield, the rewrite must be + // delayed, otherwise we may miss an opportunity for a pair. + // + // Also rewrite frequent pairs + // aload_0, aload_1 + // aload_0, iload_1 + // These bytecodes with a small amount of code are most profitable + // to rewrite + if (RewriteFrequentPairs && rc == may_rewrite) { + Label rewrite, done; + const Register bc = x14; + + // get next bytecode + __ load_unsigned_byte(x11, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); + + // if _getfield then wait with rewrite + __ mv(t1, Bytecodes::Bytecodes::_getfield); + __ beq(x11, t1, done); + + // if _igetfield then rewrite to _fast_iaccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ mv(t1, Bytecodes::_fast_igetfield); + __ mv(bc, Bytecodes::_fast_iaccess_0); + __ beq(x11, t1, rewrite); + + // if _agetfield then rewrite to _fast_aaccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ mv(t1, Bytecodes::_fast_agetfield); + __ mv(bc, Bytecodes::_fast_aaccess_0); + __ beq(x11, t1, rewrite); + + // if _fgetfield then rewrite to _fast_faccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ mv(t1, Bytecodes::_fast_fgetfield); + __ mv(bc, Bytecodes::_fast_faccess_0); + __ beq(x11, t1, rewrite); + + // else rewrite to _fast_aload0 + assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ mv(bc, Bytecodes::Bytecodes::_fast_aload_0); + + // rewrite + // bc: new bytecode + __ bind(rewrite); + patch_bytecode(Bytecodes::_aload_0, bc, x11, false); + + __ bind(done); + } + + // Do actual aload_0 (must do this after patch_bytecode which might call VM and GC might change oop). + aload(0); +} + +void TemplateTable::istore() +{ + transition(itos, vtos); + locals_index(x11); + __ sw(x10, iaddress(x11, t0, _masm)); +} + +void TemplateTable::lstore() +{ + transition(ltos, vtos); + locals_index(x11); + __ sd(x10, laddress(x11, t0, _masm)); +} + +void TemplateTable::fstore() { + transition(ftos, vtos); + locals_index(x11); + __ fsw(f10, iaddress(x11, t0, _masm)); +} + +void TemplateTable::dstore() { + transition(dtos, vtos); + locals_index(x11); + __ fsd(f10, daddress(x11, t0, _masm)); +} + +void TemplateTable::astore() +{ + transition(vtos, vtos); + __ pop_ptr(x10); + locals_index(x11); + __ sd(x10, aaddress(x11, t0, _masm)); +} + +void TemplateTable::wide_istore() { + transition(vtos, vtos); + __ pop_i(); + locals_index_wide(x11); + __ sw(x10, iaddress(x11, t0, _masm)); +} + +void TemplateTable::wide_lstore() { + transition(vtos, vtos); + __ pop_l(); + locals_index_wide(x11); + __ sd(x10, laddress(x11, t0, _masm)); +} + +void TemplateTable::wide_fstore() { + transition(vtos, vtos); + __ pop_f(); + locals_index_wide(x11); + __ fsw(f10, faddress(x11, t0, _masm)); +} + +void TemplateTable::wide_dstore() { + transition(vtos, vtos); + __ pop_d(); + locals_index_wide(x11); + __ fsd(f10, daddress(x11, t0, _masm)); +} + +void TemplateTable::wide_astore() { + transition(vtos, vtos); + __ pop_ptr(x10); + locals_index_wide(x11); + __ sd(x10, aaddress(x11, t0, _masm)); +} + +void TemplateTable::iastore() { + transition(itos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // x10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_INT) >> 2); + __ shadd(t0, x11, x13, t0, 2); + __ access_store_at(T_INT, IN_HEAP | IS_ARRAY, Address(t0, 0), x10, noreg, noreg); +} + +void TemplateTable::lastore() { + transition(ltos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // x10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_LONG) >> 3); + __ shadd(t0, x11, x13, t0, 3); + __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY, Address(t0, 0), x10, noreg, noreg); +} + +void TemplateTable::fastore() { + transition(ftos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // f10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_FLOAT) >> 2); + __ shadd(t0, x11, x13, t0, 2); + __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY, Address(t0, 0), noreg /* ftos */, noreg, noreg); +} + +void TemplateTable::dastore() { + transition(dtos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // f10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) >> 3); + __ shadd(t0, x11, x13, t0, 3); + __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY, Address(t0, 0), noreg /* dtos */, noreg, noreg); +} + +void TemplateTable::aastore() { + Label is_null, ok_is_subtype, done; + transition(vtos, vtos); + // stack: ..., array, index, value + __ ld(x10, at_tos()); // value + __ ld(x12, at_tos_p1()); // index + __ ld(x13, at_tos_p2()); // array + + index_check(x13, x12); // kills x11 + __ add(x14, x12, arrayOopDesc::base_offset_in_bytes(T_OBJECT) >> LogBytesPerHeapOop); + __ shadd(x14, x14, x13, x14, LogBytesPerHeapOop); + + Address element_address(x14, 0); + + // do array store check - check for NULL value first + __ beqz(x10, is_null); + + // Move subklass into x11 + __ load_klass(x11, x10); + // Move superklass into x10 + __ load_klass(x10, x13); + __ ld(x10, Address(x10, + ObjArrayKlass::element_klass_offset())); + // Compress array + index * oopSize + 12 into a single register. Frees x12. + + // Generate subtype check. Blows x12, x15 + // Superklass in x10. Subklass in x11. + __ gen_subtype_check(x11, ok_is_subtype); //todo + + // Come here on failure + // object is at TOS + __ j(Interpreter::_throw_ArrayStoreException_entry); + + // Come here on success + __ bind(ok_is_subtype); + + // Get the value we will store + __ ld(x10, at_tos()); + // Now store using the appropriate barrier + do_oop_store(_masm, element_address, x10, IS_ARRAY); + __ j(done); + + // Have a NULL in x10, x13=array, x12=index. Store NULL at ary[idx] + __ bind(is_null); + __ profile_null_seen(x12); + + // Store a NULL + do_oop_store(_masm, element_address, noreg, IS_ARRAY); + + // Pop stack arguments + __ bind(done); + __ add(esp, esp, 3 * Interpreter::stackElementSize); + +} + +void TemplateTable::bastore() +{ + transition(itos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // x10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(x12, x13); + __ lwu(x12, Address(x12, Klass::layout_helper_offset())); + Label L_skip; + __ andi(t0, x12, Klass::layout_helper_boolean_diffbit()); + __ beqz(t0, L_skip); + __ andi(x10, x10, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_BYTE) >> 0); + + __ add(x11, x13, x11); + __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY, Address(x11, 0), x10, noreg, noreg); +} + +void TemplateTable::castore() +{ + transition(itos, vtos); + __ pop_i(x11); + __ pop_ptr(x13); + // x10: value + // x11: index + // x13: array + index_check(x13, x11); // prefer index in x11 + __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1); + __ shadd(t0, x11, x13, t0, 1); + __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY, Address(t0, 0), x10, noreg, noreg); +} + +void TemplateTable::sastore() +{ + castore(); +} + +void TemplateTable::istore(int n) +{ + transition(itos, vtos); + __ sd(x10, iaddress(n)); +} + +void TemplateTable::lstore(int n) +{ + transition(ltos, vtos); + __ sd(x10, laddress(n)); +} + +void TemplateTable::fstore(int n) +{ + transition(ftos, vtos); + __ fsw(f10, faddress(n)); +} + +void TemplateTable::dstore(int n) +{ + transition(dtos, vtos); + __ fsd(f10, daddress(n)); +} + +void TemplateTable::astore(int n) +{ + transition(vtos, vtos); + __ pop_ptr(x10); + __ sd(x10, iaddress(n)); +} + +void TemplateTable::pop() +{ + transition(vtos, vtos); + __ addi(esp, esp, Interpreter::stackElementSize); +} + +void TemplateTable::pop2() +{ + transition(vtos, vtos); + __ addi(esp, esp, 2 * Interpreter::stackElementSize); +} + +void TemplateTable::dup() +{ + transition(vtos, vtos); + __ ld(x10, Address(esp, 0)); + __ push_reg(x10); + // stack: ..., a, a +} + +void TemplateTable::dup_x1() +{ + transition(vtos, vtos); + // stack: ..., a, b + __ ld(x10, at_tos()); // load b + __ ld(x12, at_tos_p1()); // load a + __ sd(x10, at_tos_p1()); // store b + __ sd(x12, at_tos()); // store a + __ push_reg(x10); // push b + // stack: ..., b, a, b +} + +void TemplateTable::dup_x2() +{ + transition(vtos, vtos); + // stack: ..., a, b, c + __ ld(x10, at_tos()); // load c + __ ld(x12, at_tos_p2()); // load a + __ sd(x10, at_tos_p2()); // store c in a + __ push_reg(x10); // push c + // stack: ..., c, b, c, c + __ ld(x10, at_tos_p2()); // load b + __ sd(x12, at_tos_p2()); // store a in b + // stack: ..., c, a, c, c + __ sd(x10, at_tos_p1()); // store b in c + // stack: ..., c, a, b, c +} + +void TemplateTable::dup2() +{ + transition(vtos, vtos); + // stack: ..., a, b + __ ld(x10, at_tos_p1()); // load a + __ push_reg(x10); // push a + __ ld(x10, at_tos_p1()); // load b + __ push_reg(x10); // push b + // stack: ..., a, b, a, b +} + +void TemplateTable::dup2_x1() +{ + transition(vtos, vtos); + // stack: ..., a, b, c + __ ld(x12, at_tos()); // load c + __ ld(x10, at_tos_p1()); // load b + __ push_reg(x10); // push b + __ push_reg(x12); // push c + // stack: ..., a, b, c, b, c + __ sd(x12, at_tos_p3()); // store c in b + // stack: ..., a, c, c, b, c + __ ld(x12, at_tos_p4()); // load a + __ sd(x12, at_tos_p2()); // store a in 2nd c + // stack: ..., a, c, a, b, c + __ sd(x10, at_tos_p4()); // store b in a + // stack: ..., b, c, a, b, c +} + +void TemplateTable::dup2_x2() +{ + transition(vtos, vtos); + // stack: ..., a, b, c, d + __ ld(x12, at_tos()); // load d + __ ld(x10, at_tos_p1()); // load c + __ push_reg(x10); // push c + __ push_reg(x12); // push d + // stack: ..., a, b, c, d, c, d + __ ld(x10, at_tos_p4()); // load b + __ sd(x10, at_tos_p2()); // store b in d + __ sd(x12, at_tos_p4()); // store d in b + // stack: ..., a, d, c, b, c, d + __ ld(x12, at_tos_p5()); // load a + __ ld(x10, at_tos_p3()); // load c + __ sd(x12, at_tos_p3()); // store a in c + __ sd(x10, at_tos_p5()); // store c in a + // stack: ..., c, d, a, b, c, d +} + +void TemplateTable::swap() +{ + transition(vtos, vtos); + // stack: ..., a, b + __ ld(x12, at_tos_p1()); // load a + __ ld(x10, at_tos()); // load b + __ sd(x12, at_tos()); // store a in b + __ sd(x10, at_tos_p1()); // store b in a + // stack: ..., b, a +} + +void TemplateTable::iop2(Operation op) +{ + transition(itos, itos); + // x10 <== x11 op x10 + __ pop_i(x11); + switch (op) { + case add : __ addw(x10, x11, x10); break; + case sub : __ subw(x10, x11, x10); break; + case mul : __ mulw(x10, x11, x10); break; + case _and : __ andrw(x10, x11, x10); break; + case _or : __ orrw(x10, x11, x10); break; + case _xor : __ xorrw(x10, x11, x10); break; + case shl : __ sllw(x10, x11, x10); break; + case shr : __ sraw(x10, x11, x10); break; + case ushr : __ srlw(x10, x11, x10); break; + default : ShouldNotReachHere(); + } +} + +void TemplateTable::lop2(Operation op) +{ + transition(ltos, ltos); + // x10 <== x11 op x10 + __ pop_l(x11); + switch (op) { + case add : __ add(x10, x11, x10); break; + case sub : __ sub(x10, x11, x10); break; + case mul : __ mul(x10, x11, x10); break; + case _and : __ andr(x10, x11, x10); break; + case _or : __ orr(x10, x11, x10); break; + case _xor : __ xorr(x10, x11, x10); break; + default : ShouldNotReachHere(); + } +} + +void TemplateTable::idiv() +{ + transition(itos, itos); + // explicitly check for div0 + Label no_div0; + __ bnez(x10, no_div0); + __ mv(t0, Interpreter::_throw_ArithmeticException_entry); + __ jr(t0); + __ bind(no_div0); + __ pop_i(x11); + // x10 <== x11 idiv x10 + __ corrected_idivl(x10, x11, x10, /* want_remainder */ false); +} + +void TemplateTable::irem() +{ + transition(itos, itos); + // explicitly check for div0 + Label no_div0; + __ bnez(x10, no_div0); + __ mv(t0, Interpreter::_throw_ArithmeticException_entry); + __ jr(t0); + __ bind(no_div0); + __ pop_i(x11); + // x10 <== x11 irem x10 + __ corrected_idivl(x10, x11, x10, /* want_remainder */ true); +} + +void TemplateTable::lmul() +{ + transition(ltos, ltos); + __ pop_l(x11); + __ mul(x10, x10, x11); +} + +void TemplateTable::ldiv() +{ + transition(ltos, ltos); + // explicitly check for div0 + Label no_div0; + __ bnez(x10, no_div0); + __ mv(t0, Interpreter::_throw_ArithmeticException_entry); + __ jr(t0); + __ bind(no_div0); + __ pop_l(x11); + // x10 <== x11 ldiv x10 + __ corrected_idivq(x10, x11, x10, /* want_remainder */ false); +} + +void TemplateTable::lrem() +{ + transition(ltos, ltos); + // explicitly check for div0 + Label no_div0; + __ bnez(x10, no_div0); + __ mv(t0, Interpreter::_throw_ArithmeticException_entry); + __ jr(t0); + __ bind(no_div0); + __ pop_l(x11); + // x10 <== x11 lrem x10 + __ corrected_idivq(x10, x11, x10, /* want_remainder */ true); +} + +void TemplateTable::lshl() +{ + transition(itos, ltos); + // shift count is in x10 + __ pop_l(x11); + __ sll(x10, x11, x10); +} + +void TemplateTable::lshr() +{ + transition(itos, ltos); + // shift count is in x10 + __ pop_l(x11); + __ sra(x10, x11, x10); +} + +void TemplateTable::lushr() +{ + transition(itos, ltos); + // shift count is in x10 + __ pop_l(x11); + __ srl(x10, x11, x10); +} + +void TemplateTable::fop2(Operation op) +{ + transition(ftos, ftos); + switch (op) { + case add: + __ pop_f(f11); + __ fadd_s(f10, f11, f10); + break; + case sub: + __ pop_f(f11); + __ fsub_s(f10, f11, f10); + break; + case mul: + __ pop_f(f11); + __ fmul_s(f10, f11, f10); + break; + case div: + __ pop_f(f11); + __ fdiv_s(f10, f11, f10); + break; + case rem: + __ fmv_s(f11, f10); + __ pop_f(f10); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem)); + break; + default: + ShouldNotReachHere(); + } +} + +void TemplateTable::dop2(Operation op) +{ + transition(dtos, dtos); + switch (op) { + case add: + __ pop_d(f11); + __ fadd_d(f10, f11, f10); + break; + case sub: + __ pop_d(f11); + __ fsub_d(f10, f11, f10); + break; + case mul: + __ pop_d(f11); + __ fmul_d(f10, f11, f10); + break; + case div: + __ pop_d(f11); + __ fdiv_d(f10, f11, f10); + break; + case rem: + __ fmv_d(f11, f10); + __ pop_d(f10); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem)); + break; + default: + ShouldNotReachHere(); + } +} + +void TemplateTable::ineg() +{ + transition(itos, itos); + __ negw(x10, x10); +} + +void TemplateTable::lneg() +{ + transition(ltos, ltos); + __ neg(x10, x10); +} + +void TemplateTable::fneg() +{ + transition(ftos, ftos); + __ fneg_s(f10, f10); +} + +void TemplateTable::dneg() +{ + transition(dtos, dtos); + __ fneg_d(f10, f10); +} + +void TemplateTable::iinc() +{ + transition(vtos, vtos); + __ load_signed_byte(x11, at_bcp(2)); // get constant + locals_index(x12); + __ ld(x10, iaddress(x12, x10, _masm)); + __ addw(x10, x10, x11); + __ sd(x10, iaddress(x12, t0, _masm)); +} + +void TemplateTable::wide_iinc() +{ + transition(vtos, vtos); + __ lwu(x11, at_bcp(2)); // get constant and index + __ revb_h_w_u(x11, x11); // reverse bytes in half-word (32bit) and zero-extend + __ zero_extend(x12, x11, 16); + __ neg(x12, x12); + __ slli(x11, x11, 32); + __ srai(x11, x11, 48); + __ ld(x10, iaddress(x12, t0, _masm)); + __ addw(x10, x10, x11); + __ sd(x10, iaddress(x12, t0, _masm)); +} + +void TemplateTable::convert() +{ + // Checking +#ifdef ASSERT + { + TosState tos_in = ilgl; + TosState tos_out = ilgl; + switch (bytecode()) { + case Bytecodes::_i2l: // fall through + case Bytecodes::_i2f: // fall through + case Bytecodes::_i2d: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_in = itos; break; + case Bytecodes::_l2i: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_l2d: tos_in = ltos; break; + case Bytecodes::_f2i: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_f2d: tos_in = ftos; break; + case Bytecodes::_d2i: // fall through + case Bytecodes::_d2l: // fall through + case Bytecodes::_d2f: tos_in = dtos; break; + default : ShouldNotReachHere(); + } + switch (bytecode()) { + case Bytecodes::_l2i: // fall through + case Bytecodes::_f2i: // fall through + case Bytecodes::_d2i: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_out = itos; break; + case Bytecodes::_i2l: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_d2l: tos_out = ltos; break; + case Bytecodes::_i2f: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_d2f: tos_out = ftos; break; + case Bytecodes::_i2d: // fall through + case Bytecodes::_l2d: // fall through + case Bytecodes::_f2d: tos_out = dtos; break; + default : ShouldNotReachHere(); + } + transition(tos_in, tos_out); + } +#endif // ASSERT + + // Conversion + switch (bytecode()) { + case Bytecodes::_i2l: + __ sign_extend(x10, x10, 32); + break; + case Bytecodes::_i2f: + __ fcvt_s_w(f10, x10); + break; + case Bytecodes::_i2d: + __ fcvt_d_w(f10, x10); + break; + case Bytecodes::_i2b: + __ sign_extend(x10, x10, 8); + break; + case Bytecodes::_i2c: + __ zero_extend(x10, x10, 16); + break; + case Bytecodes::_i2s: + __ sign_extend(x10, x10, 16); + break; + case Bytecodes::_l2i: + __ addw(x10, x10, zr); + break; + case Bytecodes::_l2f: + __ fcvt_s_l(f10, x10); + break; + case Bytecodes::_l2d: + __ fcvt_d_l(f10, x10); + break; + case Bytecodes::_f2i: + __ fcvt_w_s_safe(x10, f10); + break; + case Bytecodes::_f2l: + __ fcvt_l_s_safe(x10, f10); + break; + case Bytecodes::_f2d: + __ fcvt_d_s(f10, f10); + break; + case Bytecodes::_d2i: + __ fcvt_w_d_safe(x10, f10); + break; + case Bytecodes::_d2l: + __ fcvt_l_d_safe(x10, f10); + break; + case Bytecodes::_d2f: + __ fcvt_s_d(f10, f10); + break; + default: + ShouldNotReachHere(); + } +} + +void TemplateTable::lcmp() +{ + transition(ltos, itos); + __ pop_l(x11); + __ cmp_l2i(t0, x11, x10); + __ mv(x10, t0); +} + +void TemplateTable::float_cmp(bool is_float, int unordered_result) +{ + // For instruction feq, flt and fle, the result is 0 if either operand is NaN + if (is_float) { + __ pop_f(f11); + // if unordered_result < 0: + // we want -1 for unordered or less than, 0 for equal and 1 for + // greater than. + // else: + // we want -1 for less than, 0 for equal and 1 for unordered or + // greater than. + // f11 primary, f10 secondary + __ float_compare(x10, f11, f10, unordered_result); + } else { + __ pop_d(f11); + // if unordered_result < 0: + // we want -1 for unordered or less than, 0 for equal and 1 for + // greater than. + // else: + // we want -1 for less than, 0 for equal and 1 for unordered or + // greater than. + // f11 primary, f10 secondary + __ double_compare(x10, f11, f10, unordered_result); + } +} + +void TemplateTable::branch(bool is_jsr, bool is_wide) +{ + // We might be moving to a safepoint. The thread which calls + // Interpreter::notice_safepoints() will effectively flush its cache + // when it makes a system call, but we need to do something to + // ensure that we see the changed dispatch table. + __ membar(MacroAssembler::LoadLoad); + + __ profile_taken_branch(x10, x11); + const ByteSize be_offset = MethodCounters::backedge_counter_offset() + + InvocationCounter::counter_offset(); + const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + + InvocationCounter::counter_offset(); + + // load branch displacement + if (!is_wide) { + __ lhu(x12, at_bcp(1)); + __ revb_h_h(x12, x12); // reverse bytes in half-word and sign-extend + } else { + __ lwu(x12, at_bcp(1)); + __ revb_w_w(x12, x12); // reverse bytes in word and sign-extend + } + + // Handle all the JSR stuff here, then exit. + // It's much shorter and cleaner than intermingling with the non-JSR + // normal-branch stuff occurring below. + + if (is_jsr) { + // compute return address as bci + __ ld(t1, Address(xmethod, Method::const_offset())); + __ add(t1, t1, + in_bytes(ConstMethod::codes_offset()) - (is_wide ? 5 : 3)); + __ sub(x11, xbcp, t1); + __ push_i(x11); + // Adjust the bcp by the 16-bit displacement in x12 + __ add(xbcp, xbcp, x12); + __ load_unsigned_byte(t0, Address(xbcp, 0)); + // load the next target bytecode into t0, it is the argument of dispatch_only + __ dispatch_only(vtos, /*generate_poll*/true); + return; + } + + // Normal (non-jsr) branch handling + + // Adjust the bcp by the displacement in x12 + __ add(xbcp, xbcp, x12); + + assert(UseLoopCounter || !UseOnStackReplacement, + "on-stack-replacement requires loop counters"); + Label backedge_counter_overflow; + Label dispatch; + if (UseLoopCounter) { + // increment backedge counter for backward branches + // x10: MDO + // x11: MDO bumped taken-count + // x12: target offset + __ bgtz(x12, dispatch); // count only if backward branch + + // check if MethodCounters exists + Label has_counters; + __ ld(t0, Address(xmethod, Method::method_counters_offset())); + __ bnez(t0, has_counters); + __ push_reg(x10); + __ push_reg(x11); + __ push_reg(x12); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::build_method_counters), xmethod); + __ pop_reg(x12); + __ pop_reg(x11); + __ pop_reg(x10); + __ ld(t0, Address(xmethod, Method::method_counters_offset())); + __ beqz(t0, dispatch); // No MethodCounters allocated, OutOfMemory + __ bind(has_counters); + + Label no_mdo; + int increment = InvocationCounter::count_increment; + if (ProfileInterpreter) { + // Are we profiling? + __ ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); + __ beqz(x11, no_mdo); + // Increment the MDO backedge counter + const Address mdo_backedge_counter(x11, in_bytes(MethodData::backedge_counter_offset()) + + in_bytes(InvocationCounter::counter_offset())); + const Address mask(x11, in_bytes(MethodData::backedge_mask_offset())); + __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, + x10, t0, false, + UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); + __ j(dispatch); + } + __ bind(no_mdo); + // Increment backedge counter in MethodCounters* + __ ld(t0, Address(xmethod, Method::method_counters_offset())); + const Address mask(t0, in_bytes(MethodCounters::backedge_mask_offset())); + __ increment_mask_and_jump(Address(t0, be_offset), increment, mask, + x10, t1, false, + UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); + __ bind(dispatch); + } + + // Pre-load the next target bytecode into t0 + __ load_unsigned_byte(t0, Address(xbcp, 0)); + + // continue with the bytecode @ target + // t0: target bytecode + // xbcp: target bcp + __ dispatch_only(vtos, /*generate_poll*/true); + + if (UseLoopCounter && UseOnStackReplacement) { + // invocation counter overflow + __ bind(backedge_counter_overflow); + __ neg(x12, x12); + __ add(x12, x12, xbcp); // branch xbcp + // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::frequency_counter_overflow), + x12); + __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode + + // x10: osr nmethod (osr ok) or NULL (osr not possible) + // w11: target bytecode + // x12: temporary + __ beqz(x10, dispatch); // test result -- no osr if null + // nmethod may have been invalidated (VM may block upon call_VM return) + __ lbu(x12, Address(x10, nmethod::state_offset())); + if (nmethod::in_use != 0) { + __ sub(x12, x12, nmethod::in_use); + } + __ bnez(x12, dispatch); + + // We have the address of an on stack replacement routine in x10 + // We need to prepare to execute the OSR method. First we must + // migrate the locals and monitors off of the stack. + + __ mv(x9, x10); // save the nmethod + + call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); + + // x10 is OSR buffer, move it to expected parameter location + __ mv(j_rarg0, x10); + + // remove activation + // get sender esp + __ ld(esp, + Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); + // remove frame anchor + __ leave(); + // Ensure compiled code always sees stack at proper alignment + __ andi(sp, esp, -16); + + // and begin the OSR nmethod + __ ld(t0, Address(x9, nmethod::osr_entry_point_offset())); + __ jr(t0); + } +} + +void TemplateTable::if_0cmp(Condition cc) +{ + transition(itos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + + __ addw(x10, x10, zr); + switch (cc) { + case equal: + __ bnez(x10, not_taken); + break; + case not_equal: + __ beqz(x10, not_taken); + break; + case less: + __ bgez(x10, not_taken); + break; + case less_equal: + __ bgtz(x10, not_taken); + break; + case greater: + __ blez(x10, not_taken); + break; + case greater_equal: + __ bltz(x10, not_taken); + break; + default: + break; + } + + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(x10); +} + +void TemplateTable::if_icmp(Condition cc) +{ + transition(itos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ pop_i(x11); + __ addw(x10, x10, zr); + switch (cc) { + case equal: + __ bne(x11, x10, not_taken); + break; + case not_equal: + __ beq(x11, x10, not_taken); + break; + case less: + __ bge(x11, x10, not_taken); + break; + case less_equal: + __ bgt(x11, x10, not_taken); + break; + case greater: + __ ble(x11, x10, not_taken); + break; + case greater_equal: + __ blt(x11, x10, not_taken); + break; + default: + break; + } + + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(x10); +} + +void TemplateTable::if_nullcmp(Condition cc) +{ + transition(atos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + if (cc == equal) { + __ bnez(x10, not_taken); + } else { + __ beqz(x10, not_taken); + } + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(x10); +} + +void TemplateTable::if_acmp(Condition cc) +{ + transition(atos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ pop_ptr(x11); + + if (cc == equal) { + __ bne(x11, x10, not_taken); + } else if (cc == not_equal) { + __ beq(x11, x10, not_taken); + } + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(x10); +} + +void TemplateTable::ret() { + transition(vtos, vtos); + // We might be moving to a safepoint. The thread which calls + // Interpreter::notice_safepoints() will effectively flush its cache + // when it makes a system call, but we need to do something to + // ensure that we see the changed dispatch table. + __ membar(MacroAssembler::LoadLoad); + + locals_index(x11); + __ ld(x11, aaddress(x11, t1, _masm)); // get return bci, compute return bcp + __ profile_ret(x11, x12); + __ ld(xbcp, Address(xmethod, Method::const_offset())); + __ add(xbcp, xbcp, x11); + __ addi(xbcp, xbcp, in_bytes(ConstMethod::codes_offset())); + __ dispatch_next(vtos, 0, /*generate_poll*/true); +} + +void TemplateTable::wide_ret() { + transition(vtos, vtos); + locals_index_wide(x11); + __ ld(x11, aaddress(x11, t0, _masm)); // get return bci, compute return bcp + __ profile_ret(x11, x12); + __ ld(xbcp, Address(xmethod, Method::const_offset())); + __ add(xbcp, xbcp, x11); + __ add(xbcp, xbcp, in_bytes(ConstMethod::codes_offset())); + __ dispatch_next(vtos, 0, /*generate_poll*/true); +} + +void TemplateTable::tableswitch() { + Label default_case, continue_execution; + transition(itos, vtos); + // align xbcp + __ la(x11, at_bcp(BytesPerInt)); + __ andi(x11, x11, -BytesPerInt); + // load lo & hi + __ lwu(x12, Address(x11, BytesPerInt)); + __ lwu(x13, Address(x11, 2 * BytesPerInt)); + __ revb_w_w(x12, x12); // reverse bytes in word (32bit) and sign-extend + __ revb_w_w(x13, x13); // reverse bytes in word (32bit) and sign-extend + // check against lo & hi + __ blt(x10, x12, default_case); + __ bgt(x10, x13, default_case); + // lookup dispatch offset + __ subw(x10, x10, x12); + __ shadd(x13, x10, x11, t0, 2); + __ lwu(x13, Address(x13, 3 * BytesPerInt)); + __ profile_switch_case(x10, x11, x12); + // continue execution + __ bind(continue_execution); + __ revb_w_w(x13, x13); // reverse bytes in word (32bit) and sign-extend + __ add(xbcp, xbcp, x13); + __ load_unsigned_byte(t0, Address(xbcp)); + __ dispatch_only(vtos, /*generate_poll*/true); + // handle default + __ bind(default_case); + __ profile_switch_default(x10); + __ lwu(x13, Address(x11, 0)); + __ j(continue_execution); +} + +void TemplateTable::lookupswitch() { + transition(itos, itos); + __ stop("lookupswitch bytecode should have been rewritten"); +} + +void TemplateTable::fast_linearswitch() { + transition(itos, vtos); + Label loop_entry, loop, found, continue_execution; + // bswap x10 so we can avoid bswapping the table entries + __ revb_w_w(x10, x10); // reverse bytes in word (32bit) and sign-extend + // align xbcp + __ la(x9, at_bcp(BytesPerInt)); // btw: should be able to get rid of + // this instruction (change offsets + // below) + __ andi(x9, x9, -BytesPerInt); + // set counter + __ lwu(x11, Address(x9, BytesPerInt)); + __ revb_w(x11, x11); + __ j(loop_entry); + // table search + __ bind(loop); + __ shadd(t0, x11, x9, t0, 3); + __ lw(t0, Address(t0, 2 * BytesPerInt)); + __ beq(x10, t0, found); + __ bind(loop_entry); + __ addi(x11, x11, -1); + __ bgez(x11, loop); + // default case + __ profile_switch_default(x10); + __ lwu(x13, Address(x9, 0)); + __ j(continue_execution); + // entry found -> get offset + __ bind(found); + __ shadd(t0, x11, x9, t0, 3); + __ lwu(x13, Address(t0, 3 * BytesPerInt)); + __ profile_switch_case(x11, x10, x9); + // continue execution + __ bind(continue_execution); + __ revb_w_w(x13, x13); // reverse bytes in word (32bit) and sign-extend + __ add(xbcp, xbcp, x13); + __ lbu(t0, Address(xbcp, 0)); + __ dispatch_only(vtos, /*generate_poll*/true); +} + +void TemplateTable::fast_binaryswitch() { + transition(itos, vtos); + // Implementation using the following core algorithm: + // + // int binary_search(int key, LookupswitchPair* array, int n) + // binary_search start: + // #Binary search according to "Methodik des Programmierens" by + // # Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. + // int i = 0; + // int j = n; + // while (i + 1 < j) do + // # invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) + // # with Q: for all i: 0 <= i < n: key < a[i] + // # where a stands for the array and assuming that the (inexisting) + // # element a[n] is infinitely big. + // int h = (i + j) >> 1 + // # i < h < j + // if (key < array[h].fast_match()) + // then [j = h] + // else [i = h] + // end + // # R: a[i] <= key < a[i+1] or Q + // # (i.e., if key is within array, i is the correct index) + // return i + // binary_search end + + + // Register allocation + const Register key = x10; // already set (tosca) + const Register array = x11; + const Register i = x12; + const Register j = x13; + const Register h = x14; + const Register temp = x15; + + // Find array start + __ la(array, at_bcp(3 * BytesPerInt)); // btw: should be able to + // get rid of this + // instruction (change + // offsets below) + __ andi(array, array, -BytesPerInt); + + // Initialize i & j + __ mv(i, zr); // i = 0 + __ lwu(j, Address(array, -BytesPerInt)); // j = length(array) + + // Convert j into native byteordering + __ revb_w(j, j); + + // And start + Label entry; + __ j(entry); + + // binary search loop + { + Label loop; + __ bind(loop); + __ addw(h, i, j); // h = i + j + __ srliw(h, h, 1); // h = (i + j) >> 1 + // if [key < array[h].fast_match()] + // then [j = h] + // else [i = h] + // Convert array[h].match to native byte-ordering before compare + __ shadd(temp, h, array, temp, 3); + __ ld(temp, Address(temp, 0)); + __ revb_w_w(temp, temp); // reverse bytes in word (32bit) and sign-extend + + Label L_done, L_greater; + __ bge(key, temp, L_greater); + // if [key < array[h].fast_match()] then j = h + __ mv(j, h); + __ j(L_done); + __ bind(L_greater); + // if [key >= array[h].fast_match()] then i = h + __ mv(i, h); + __ bind(L_done); + + // while [i + 1 < j] + __ bind(entry); + __ addiw(h, i, 1); // i + 1 + __ blt(h, j, loop); // i + 1 < j + } + + // end of binary search, result index is i (must check again!) + Label default_case; + // Convert array[i].match to native byte-ordering before compare + __ shadd(temp, i, array, temp, 3); + __ ld(temp, Address(temp, 0)); + __ revb_w_w(temp, temp); // reverse bytes in word (32bit) and sign-extend + __ bne(key, temp, default_case); + + // entry found -> j = offset + __ shadd(temp, i, array, temp, 3); + __ lwu(j, Address(temp, BytesPerInt)); + __ profile_switch_case(i, key, array); + __ revb_w_w(j, j); // reverse bytes in word (32bit) and sign-extend + + __ add(temp, xbcp, j); + __ load_unsigned_byte(t0, Address(temp, 0)); + + __ add(xbcp, xbcp, j); + __ la(xbcp, Address(xbcp, 0)); + __ dispatch_only(vtos, /*generate_poll*/true); + + // default case -> j = default offset + __ bind(default_case); + __ profile_switch_default(i); + __ lwu(j, Address(array, -2 * BytesPerInt)); + __ revb_w_w(j, j); // reverse bytes in word (32bit) and sign-extend + + __ add(temp, xbcp, j); + __ load_unsigned_byte(t0, Address(temp, 0)); + + __ add(xbcp, xbcp, j); + __ la(xbcp, Address(xbcp, 0)); + __ dispatch_only(vtos, /*generate_poll*/true); +} + +void TemplateTable::_return(TosState state) +{ + transition(state, state); + assert(_desc->calls_vm(), + "inconsistent calls_vm information"); // call in remove_activation + + if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { + assert(state == vtos, "only valid state"); + + __ ld(c_rarg1, aaddress(0)); + __ load_klass(x13, c_rarg1); + __ lwu(x13, Address(x13, Klass::access_flags_offset())); + Label skip_register_finalizer; + __ andi(t0, x13, JVM_ACC_HAS_FINALIZER); + __ beqz(t0, skip_register_finalizer); + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), c_rarg1); + + __ bind(skip_register_finalizer); + } + + // Issue a StoreStore barrier after all stores but before return + // from any constructor for any class with a final field. We don't + // know if this is a finalizer, so we always do so. + if (_desc->bytecode() == Bytecodes::_return) { + __ membar(MacroAssembler::StoreStore); + } + + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(x10); + } + + __ remove_activation(state); + __ ret(); +} + + +// ---------------------------------------------------------------------------- +// Volatile variables demand their effects be made known to all CPU's +// in order. Store buffers on most chips allow reads & writes to +// reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode +// without some kind of memory barrier (i.e., it's not sufficient that +// the interpreter does not reorder volatile references, the hardware +// also must not reorder them). +// +// According to the new Java Memory Model (JMM): +// (1) All volatiles are serialized wrt to each other. ALSO reads & +// writes act as aquire & release, so: +// (2) A read cannot let unrelated NON-volatile memory refs that +// happen after the read float up to before the read. It's OK for +// non-volatile memory refs that happen before the volatile read to +// float down below it. +// (3) Similar a volatile write cannot let unrelated NON-volatile +// memory refs that happen BEFORE the write float down to after the +// write. It's OK for non-volatile memory refs that happen after the +// volatile write to float up before it. +// +// We only put in barriers around volatile refs (they are expensive), +// not _between_ memory refs (that would require us to track the +// flavor of the previous memory refs). Requirements (2) and (3) +// require some barriers before volatile stores and after volatile +// loads. These nearly cover requirement (1) but miss the +// volatile-store-volatile-load case. This final case is placed after +// volatile-stores although it could just as well go before +// volatile-loads. + +void TemplateTable::resolve_cache_and_index(int byte_no, + Register Rcache, + Register index, + size_t index_size) { + const Register temp = x9; + assert_different_registers(Rcache, index, temp); + + Label resolved, clinit_barrier_slow; + + Bytecodes::Code code = bytecode(); + switch (code) { + case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break; + case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break; + default: break; + } + + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); + __ mv(t0, (int) code); + __ beq(temp, t0, resolved); + + // resolve first time through + // Class initialization barrier slow path lands here as well. + __ bind(clinit_barrier_slow); + + address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache); + __ mv(temp, (int) code); + __ call_VM(noreg, entry, temp); + + // Update registers with resolved info + __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); + // n.b. unlike x86 Rcache is now rcpool plus the indexed offset + // so all clients ofthis method must be modified accordingly + __ bind(resolved); + + // Class initialization barrier for static methods + if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) { + __ load_resolved_method_at_index(byte_no, temp, Rcache); + __ load_method_holder(temp, temp); + __ clinit_barrier(temp, t0, NULL, &clinit_barrier_slow); + } +} + +// The Rcache and index registers must be set before call +// n.b unlike x86 cache already includes the index offset +void TemplateTable::load_field_cp_cache_entry(Register obj, + Register cache, + Register index, + Register off, + Register flags, + bool is_static = false) { + assert_different_registers(cache, index, flags, off); + + ByteSize cp_base_offset = ConstantPoolCache::base_offset(); + // Field offset + __ ld(off, Address(cache, in_bytes(cp_base_offset + + ConstantPoolCacheEntry::f2_offset()))); + // Flags + __ lwu(flags, Address(cache, in_bytes(cp_base_offset + + ConstantPoolCacheEntry::flags_offset()))); + + // klass overwrite register + if (is_static) { + __ ld(obj, Address(cache, in_bytes(cp_base_offset + + ConstantPoolCacheEntry::f1_offset()))); + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + __ ld(obj, Address(obj, mirror_offset)); + __ resolve_oop_handle(obj); + } +} + +void TemplateTable::load_invoke_cp_cache_entry(int byte_no, + Register method, + Register itable_index, + Register flags, + bool is_invokevirtual, + bool is_invokevfinal, /*unused*/ + bool is_invokedynamic) { + // setup registers + const Register cache = t1; + const Register index = x14; + assert_different_registers(method, flags); + assert_different_registers(method, cache, index); + assert_different_registers(itable_index, flags); + assert_different_registers(itable_index, cache, index); + // determine constant pool cache field offsets + assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); + const int method_offset = in_bytes(ConstantPoolCache::base_offset() + + (is_invokevirtual ? + ConstantPoolCacheEntry::f2_offset() : + ConstantPoolCacheEntry::f1_offset())); + const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::flags_offset()); + // access constant pool cache fields + const int index_offset = in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()); + + const size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); + resolve_cache_and_index(byte_no, cache, index, index_size); + __ ld(method, Address(cache, method_offset)); + + if (itable_index != noreg) { + __ ld(itable_index, Address(cache, index_offset)); + } + __ lwu(flags, Address(cache, flags_offset)); +} + +// The registers cache and index expected to be set before call. +// Correct values of the cache and index registers are preserved. +void TemplateTable::jvmti_post_field_access(Register cache, Register index, + bool is_static, bool has_tos) { + // do the JVMTI work here to avoid disturbing the register state below + // We use c_rarg registers here beacause we want to use the register used in + // the call to the VM + if (JvmtiExport::can_post_field_access()) { + // Check to see if a field access watch has been set before we + // take the time to call into the VM. + Label L1; + assert_different_registers(cache, index, x10); + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), offset); + __ lwu(x10, Address(t0, offset)); + + __ beqz(x10, L1); + + __ get_cache_and_index_at_bcp(c_rarg2, c_rarg3, 1); + __ la(c_rarg2, Address(c_rarg2, in_bytes(ConstantPoolCache::base_offset()))); + + if (is_static) { + __ mv(c_rarg1, zr); // NULL object reference + } else { + __ ld(c_rarg1, at_tos()); // get object pointer without popping it + __ verify_oop(c_rarg1); + } + // c_rarg1: object pointer or NULL + // c_rarg2: cache entry pointer + // c_rarg3: jvalue object on the stack + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_access), + c_rarg1, c_rarg2, c_rarg3); + __ get_cache_and_index_at_bcp(cache, index, 1); + __ bind(L1); + } +} + +void TemplateTable::pop_and_check_object(Register r) +{ + __ pop_ptr(r); + __ null_check(r); // for field access must check obj. + __ verify_oop(r); +} + +void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) +{ + const Register cache = x12; + const Register index = x13; + const Register obj = x14; + const Register off = x9; + const Register flags = x10; + const Register raw_flags = x16; + const Register bc = x14; // uses same reg as obj, so don't mix them + + resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); + jvmti_post_field_access(cache, index, is_static, false); + load_field_cp_cache_entry(obj, cache, index, off, raw_flags, is_static); + + if (!is_static) { + // obj is on the stack + pop_and_check_object(obj); + } + + __ add(off, obj, off); + const Address field(off); + + Label Done, notByte, notBool, notInt, notShort, notChar, + notLong, notFloat, notObj, notDouble; + + __ slli(flags, raw_flags, XLEN - (ConstantPoolCacheEntry::tos_state_shift + + ConstantPoolCacheEntry::tos_state_bits)); + __ srli(flags, flags, XLEN - ConstantPoolCacheEntry::tos_state_bits); + + assert(btos == 0, "change code, btos != 0"); + __ bnez(flags, notByte); + + // Dont't rewrite getstatic, only getfield + if (is_static) { + rc = may_not_rewrite; + } + + // btos + __ access_load_at(T_BYTE, IN_HEAP, x10, field, noreg, noreg); + __ push(btos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_bgetfield, bc, x11); + } + __ j(Done); + + __ bind(notByte); + __ sub(t0, flags, (u1)ztos); + __ bnez(t0, notBool); + + // ztos (same code as btos) + __ access_load_at(T_BOOLEAN, IN_HEAP, x10, field, noreg, noreg); + __ push(ztos); + // Rewirte bytecode to be faster + if (rc == may_rewrite) { + // uses btos rewriting, no truncating to t/f bit is needed for getfield + patch_bytecode(Bytecodes::_fast_bgetfield, bc, x11); + } + __ j(Done); + + __ bind(notBool); + __ sub(t0, flags, (u1)atos); + __ bnez(t0, notObj); + // atos + do_oop_load(_masm, field, x10, IN_HEAP); + __ push(atos); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_agetfield, bc, x11); + } + __ j(Done); + + __ bind(notObj); + __ sub(t0, flags, (u1)itos); + __ bnez(t0, notInt); + // itos + __ access_load_at(T_INT, IN_HEAP, x10, field, noreg, noreg); + __ addw(x10, x10, zr); // signed extended + __ push(itos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_igetfield, bc, x11); + } + __ j(Done); + + __ bind(notInt); + __ sub(t0, flags, (u1)ctos); + __ bnez(t0, notChar); + // ctos + __ access_load_at(T_CHAR, IN_HEAP, x10, field, noreg, noreg); + __ push(ctos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_cgetfield, bc, x11); + } + __ j(Done); + + __ bind(notChar); + __ sub(t0, flags, (u1)stos); + __ bnez(t0, notShort); + // stos + __ access_load_at(T_SHORT, IN_HEAP, x10, field, noreg, noreg); + __ push(stos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_sgetfield, bc, x11); + } + __ j(Done); + + __ bind(notShort); + __ sub(t0, flags, (u1)ltos); + __ bnez(t0, notLong); + // ltos + __ access_load_at(T_LONG, IN_HEAP, x10, field, noreg, noreg); + __ push(ltos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_lgetfield, bc, x11); + } + __ j(Done); + + __ bind(notLong); + __ sub(t0, flags, (u1)ftos); + __ bnez(t0, notFloat); + // ftos + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + __ push(ftos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_fgetfield, bc, x11); + } + __ j(Done); + + __ bind(notFloat); +#ifdef ASSERT + __ sub(t0, flags, (u1)dtos); + __ bnez(t0, notDouble); +#endif + // dtos + __ access_load_at(T_DOUBLE, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + __ push(dtos); + // Rewrite bytecode to be faster + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_dgetfield, bc, x11); + } +#ifdef ASSERT + __ j(Done); + + __ bind(notDouble); + __ stop("Bad state"); +#endif + + __ bind(Done); + + Label notVolatile; + __ andi(t0, raw_flags, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ bind(notVolatile); +} + +void TemplateTable::getfield(int byte_no) +{ + getfield_or_static(byte_no, false); +} + +void TemplateTable::nofast_getfield(int byte_no) { + getfield_or_static(byte_no, false, may_not_rewrite); +} + +void TemplateTable::getstatic(int byte_no) +{ + getfield_or_static(byte_no, true); +} + +// The registers cache and index expected to be set before call. +// The function may destroy various registers, just not the cache and index registers. +void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { + transition(vtos, vtos); + + ByteSize cp_base_offset = ConstantPoolCache::base_offset(); + + if (JvmtiExport::can_post_field_modification()) { + // Check to see if a field modification watch has been set before + // we take the time to call into the VM. + Label L1; + assert_different_registers(cache, index, x10); + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()), offset); + __ lwu(x10, Address(t0, offset)); + __ beqz(x10, L1); + + __ get_cache_and_index_at_bcp(c_rarg2, t0, 1); + + if (is_static) { + // Life is simple. Null out the object pointer. + __ mv(c_rarg1, zr); + } else { + // Life is harder. The stack holds the value on top, followed by + // the object. We don't know the size of the value, though; it + // could be one or two words depending on its type. As a result, + // we must find the type to determine where the object is. + __ lwu(c_rarg3, Address(c_rarg2, + in_bytes(cp_base_offset + + ConstantPoolCacheEntry::flags_offset()))); + __ srli(c_rarg3, c_rarg3, ConstantPoolCacheEntry::tos_state_shift); + ConstantPoolCacheEntry::verify_tos_state_shift(); + Label nope2, done, ok; + __ ld(c_rarg1, at_tos_p1()); // initially assume a one word jvalue + __ sub(t0, c_rarg3, ltos); + __ beqz(t0, ok); + __ sub(t0, c_rarg3, dtos); + __ bnez(t0, nope2); + __ bind(ok); + __ ld(c_rarg1, at_tos_p2()); // ltos (two word jvalue); + __ bind(nope2); + } + // cache entry pointer + __ add(c_rarg2, c_rarg2, in_bytes(cp_base_offset)); + // object (tos) + __ mv(c_rarg3, esp); + // c_rarg1: object pointer set up above (NULL if static) + // c_rarg2: cache entry pointer + // c_rarg3: jvalue object on the stack + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_modification), + c_rarg1, c_rarg2, c_rarg3); + __ get_cache_and_index_at_bcp(cache, index, 1); + __ bind(L1); + } +} + +void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) { + transition(vtos, vtos); + + const Register cache = x12; + const Register index = x13; + const Register obj = x12; + const Register off = x9; + const Register flags = x10; + const Register bc = x14; + + resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); + jvmti_post_field_mod(cache, index, is_static); + load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); + + Label Done; + __ mv(x15, flags); + + { + Label notVolatile; + __ andi(t0, x15, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); + __ bind(notVolatile); + } + + Label notByte, notBool, notInt, notShort, notChar, + notLong, notFloat, notObj, notDouble; + + __ slli(flags, flags, XLEN - (ConstantPoolCacheEntry::tos_state_shift + + ConstantPoolCacheEntry::tos_state_bits)); + __ srli(flags, flags, XLEN - ConstantPoolCacheEntry::tos_state_bits); + + assert(btos == 0, "change code, btos != 0"); + __ bnez(flags, notByte); + + // Don't rewrite putstatic, only putfield + if (is_static) { + rc = may_not_rewrite; + } + + // btos + { + __ pop(btos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); // off register as temparator register. + __ access_store_at(T_BYTE, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_bputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notByte); + __ sub(t0, flags, (u1)ztos); + __ bnez(t0, notBool); + + // ztos + { + __ pop(ztos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_BOOLEAN, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notBool); + __ sub(t0, flags, (u1)atos); + __ bnez(t0, notObj); + + // atos + { + __ pop(atos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + // Store into the field + do_oop_store(_masm, field, x10, IN_HEAP); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_aputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notObj); + __ sub(t0, flags, (u1)itos); + __ bnez(t0, notInt); + + // itos + { + __ pop(itos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_INT, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_iputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notInt); + __ sub(t0, flags, (u1)ctos); + __ bnez(t0, notChar); + + // ctos + { + __ pop(ctos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_CHAR, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_cputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notChar); + __ sub(t0, flags, (u1)stos); + __ bnez(t0, notShort); + + // stos + { + __ pop(stos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_SHORT, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_sputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notShort); + __ sub(t0, flags, (u1)ltos); + __ bnez(t0, notLong); + + // ltos + { + __ pop(ltos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_LONG, IN_HEAP, field, x10, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_lputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notLong); + __ sub(t0, flags, (u1)ftos); + __ bnez(t0, notFloat); + + // ftos + { + __ pop(ftos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos */, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_fputfield, bc, x11, true, byte_no); + } + __ j(Done); + } + + __ bind(notFloat); +#ifdef ASSERT + __ sub(t0, flags, (u1)dtos); + __ bnez(t0, notDouble); +#endif + + // dtos + { + __ pop(dtos); + // field address + if (!is_static) { + pop_and_check_object(obj); + } + __ add(off, obj, off); // if static, obj from cache, else obj from stack. + const Address field(off, 0); + __ access_store_at(T_DOUBLE, IN_HEAP, field, noreg /* dtos */, noreg, noreg); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_dputfield, bc, x11, true, byte_no); + } + } + +#ifdef ASSERT + __ j(Done); + + __ bind(notDouble); + __ stop("Bad state"); +#endif + + __ bind(Done); + + { + Label notVolatile; + __ andi(t0, x15, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore); + __ bind(notVolatile); + } +} + +void TemplateTable::putfield(int byte_no) +{ + putfield_or_static(byte_no, false); +} + +void TemplateTable::nofast_putfield(int byte_no) { + putfield_or_static(byte_no, false, may_not_rewrite); +} + +void TemplateTable::putstatic(int byte_no) { + putfield_or_static(byte_no, true); +} + +void TemplateTable::jvmti_post_fast_field_mod() +{ + if (JvmtiExport::can_post_field_modification()) { + // Check to see if a field modification watch has been set before + // we take the time to call into the VM. + Label L2; + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()), offset); + __ lwu(c_rarg3, Address(t0, offset)); + __ beqz(c_rarg3, L2); + __ pop_ptr(x9); // copy the object pointer from tos + __ verify_oop(x9); + __ push_ptr(x9); // put the object pointer back on tos + // Save tos values before call_VM() clobbers them. Since we have + // to do it for every data type, we use the saved values as the + // jvalue object. + switch (bytecode()) { // load values into the jvalue object + case Bytecodes::_fast_aputfield: __ push_ptr(x10); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ push_i(x10); break; + case Bytecodes::_fast_dputfield: __ push_d(); break; + case Bytecodes::_fast_fputfield: __ push_f(); break; + case Bytecodes::_fast_lputfield: __ push_l(x10); break; + + default: + ShouldNotReachHere(); + } + __ mv(c_rarg3, esp); // points to jvalue on the stack + // access constant pool cache entry + __ get_cache_entry_pointer_at_bcp(c_rarg2, x10, 1); + __ verify_oop(x9); + // x9: object pointer copied above + // c_rarg2: cache entry pointer + // c_rarg3: jvalue object on the stack + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_modification), + x9, c_rarg2, c_rarg3); + + switch (bytecode()) { // restore tos values + case Bytecodes::_fast_aputfield: __ pop_ptr(x10); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ pop_i(x10); break; + case Bytecodes::_fast_dputfield: __ pop_d(); break; + case Bytecodes::_fast_fputfield: __ pop_f(); break; + case Bytecodes::_fast_lputfield: __ pop_l(x10); break; + default: break; + } + __ bind(L2); + } +} + +void TemplateTable::fast_storefield(TosState state) +{ + transition(state, vtos); + + ByteSize base = ConstantPoolCache::base_offset(); + + jvmti_post_fast_field_mod(); + + // access constant pool cache + __ get_cache_and_index_at_bcp(x12, x11, 1); + + // Must prevent reordering of the following cp cache loads with bytecode load + __ membar(MacroAssembler::LoadLoad); + + // test for volatile with x13 + __ lwu(x13, Address(x12, in_bytes(base + + ConstantPoolCacheEntry::flags_offset()))); + + // replace index with field offset from cache entry + __ ld(x11, Address(x12, in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); + + { + Label notVolatile; + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); + __ bind(notVolatile); + } + + // Get object from stack + pop_and_check_object(x12); + + // field address + __ add(x11, x12, x11); + const Address field(x11, 0); + + // access field + switch (bytecode()) { + case Bytecodes::_fast_aputfield: + do_oop_store(_masm, field, x10, IN_HEAP); + break; + case Bytecodes::_fast_lputfield: + __ access_store_at(T_LONG, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_iputfield: + __ access_store_at(T_INT, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_zputfield: + __ access_store_at(T_BOOLEAN, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_bputfield: + __ access_store_at(T_BYTE, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_sputfield: + __ access_store_at(T_SHORT, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_cputfield: + __ access_store_at(T_CHAR, IN_HEAP, field, x10, noreg, noreg); + break; + case Bytecodes::_fast_fputfield: + __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos */, noreg, noreg); + break; + case Bytecodes::_fast_dputfield: + __ access_store_at(T_DOUBLE, IN_HEAP, field, noreg /* dtos */, noreg, noreg); + break; + default: + ShouldNotReachHere(); + } + + { + Label notVolatile; + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore); + __ bind(notVolatile); + } +} + +void TemplateTable::fast_accessfield(TosState state) +{ + transition(atos, state); + // Do the JVMTI work here to avoid disturbing the register state below + if (JvmtiExport::can_post_field_access()) { + // Check to see if a field access watch has been set before we + // take the time to call into the VM. + Label L1; + int32_t offset = 0; + __ la_patchable(t0, ExternalAddress((address)JvmtiExport::get_field_access_count_addr()), offset); + __ lwu(x12, Address(t0, offset)); + __ beqz(x12, L1); + // access constant pool cache entry + __ get_cache_entry_pointer_at_bcp(c_rarg2, t1, 1); + __ verify_oop(x10); + __ push_ptr(x10); // save object pointer before call_VM() clobbers it + __ mv(c_rarg1, x10); + // c_rarg1: object pointer copied above + // c_rarg2: cache entry pointer + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_access), + c_rarg1, c_rarg2); + __ pop_ptr(x10); // restore object pointer + __ bind(L1); + } + + // access constant pool cache + __ get_cache_and_index_at_bcp(x12, x11, 1); + + // Must prevent reordering of the following cp cache loads with bytecode load + __ membar(MacroAssembler::LoadLoad); + + __ ld(x11, Address(x12, in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()))); + __ lwu(x13, Address(x12, in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::flags_offset()))); + + // x10: object + __ verify_oop(x10); + __ null_check(x10); + __ add(x11, x10, x11); + const Address field(x11, 0); + + // access field + switch (bytecode()) { + case Bytecodes::_fast_agetfield: + do_oop_load(_masm, field, x10, IN_HEAP); + __ verify_oop(x10); + break; + case Bytecodes::_fast_lgetfield: + __ access_load_at(T_LONG, IN_HEAP, x10, field, noreg, noreg); + break; + case Bytecodes::_fast_igetfield: + __ access_load_at(T_INT, IN_HEAP, x10, field, noreg, noreg); + __ addw(x10, x10, zr); // signed extended + break; + case Bytecodes::_fast_bgetfield: + __ access_load_at(T_BYTE, IN_HEAP, x10, field, noreg, noreg); + break; + case Bytecodes::_fast_sgetfield: + __ access_load_at(T_SHORT, IN_HEAP, x10, field, noreg, noreg); + break; + case Bytecodes::_fast_cgetfield: + __ access_load_at(T_CHAR, IN_HEAP, x10, field, noreg, noreg); + break; + case Bytecodes::_fast_fgetfield: + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + break; + case Bytecodes::_fast_dgetfield: + __ access_load_at(T_DOUBLE, IN_HEAP, noreg /* dtos */, field, noreg, noreg); + break; + default: + ShouldNotReachHere(); + } + { + Label notVolatile; + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ bind(notVolatile); + } +} + +void TemplateTable::fast_xaccess(TosState state) +{ + transition(vtos, state); + + // get receiver + __ ld(x10, aaddress(0)); + // access constant pool cache + __ get_cache_and_index_at_bcp(x12, x13, 2); + __ ld(x11, Address(x12, in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()))); + + // make sure exception is reported in correct bcp range (getfield is + // next instruction) + __ addi(xbcp, xbcp, 1); + __ null_check(x10); + switch (state) { + case itos: + __ add(x10, x10, x11); + __ access_load_at(T_INT, IN_HEAP, x10, Address(x10, 0), noreg, noreg); + __ addw(x10, x10, zr); // signed extended + break; + case atos: + __ add(x10, x10, x11); + do_oop_load(_masm, Address(x10, 0), x10, IN_HEAP); + __ verify_oop(x10); + break; + case ftos: + __ add(x10, x10, x11); + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, Address(x10), noreg, noreg); + break; + default: + ShouldNotReachHere(); + } + + { + Label notVolatile; + __ lwu(x13, Address(x12, in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::flags_offset()))); + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_volatile_shift); + __ beqz(t0, notVolatile); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ bind(notVolatile); + } + + __ sub(xbcp, xbcp, 1); +} + +//----------------------------------------------------------------------------- +// Calls + +void TemplateTable::prepare_invoke(int byte_no, + Register method, // linked method (or i-klass) + Register index, // itable index, MethodType, etc. + Register recv, // if caller wants to see it + Register flags // if caller wants to test it + ) { + // determine flags + const Bytecodes::Code code = bytecode(); + const bool is_invokeinterface = code == Bytecodes::_invokeinterface; + const bool is_invokedynamic = code == Bytecodes::_invokedynamic; + const bool is_invokehandle = code == Bytecodes::_invokehandle; + const bool is_invokevirtual = code == Bytecodes::_invokevirtual; + const bool is_invokespecial = code == Bytecodes::_invokespecial; + const bool load_receiver = (recv != noreg); + const bool save_flags = (flags != noreg); + assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); + assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); + assert(flags == noreg || flags == x13, ""); + assert(recv == noreg || recv == x12, ""); + + // setup registers & access constant pool cache + if (recv == noreg) { + recv = x12; + } + if (flags == noreg) { + flags = x13; + } + assert_different_registers(method, index, recv, flags); + + // save 'interpreter return address' + __ save_bcp(); + + load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); + + // maybe push appendix to arguments (just before return address) + if (is_invokedynamic || is_invokehandle) { + Label L_no_push; + __ andi(t0, flags, 1UL << ConstantPoolCacheEntry::has_appendix_shift); + __ beqz(t0, L_no_push); + // Push the appendix as a trailing parameter. + // This must be done before we get the receiver, + // since the parameter_size includes it. + __ push_reg(x9); + __ mv(x9, index); + __ load_resolved_reference_at_index(index, x9); + __ pop_reg(x9); + __ push_reg(index); // push appendix (MethodType, CallSite, etc.) + __ bind(L_no_push); + } + + // load receiver if needed (note: no return address pushed yet) + if (load_receiver) { + __ andi(recv, flags, ConstantPoolCacheEntry::parameter_size_mask); // parameter_size_mask = 1 << 8 + __ shadd(t0, recv, esp, t0, 3); + __ ld(recv, Address(t0, -Interpreter::expr_offset_in_bytes(1))); + __ verify_oop(recv); + } + + // compute return type + __ slli(t1, flags, XLEN - (ConstantPoolCacheEntry::tos_state_shift + ConstantPoolCacheEntry::tos_state_bits)); + __ srli(t1, t1, XLEN - ConstantPoolCacheEntry::tos_state_bits); // (1 << 5) - 4 --> 28~31==> t1:0~3 + + // load return address + { + const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); + __ mv(t0, table_addr); + __ shadd(t0, t1, t0, t1, 3); + __ ld(ra, Address(t0, 0)); + } +} + +void TemplateTable::invokevirtual_helper(Register index, + Register recv, + Register flags) +{ + // Uses temporary registers x10, x13 + assert_different_registers(index, recv, x10, x13); + // Test for an invoke of a final method + Label notFinal; + __ andi(t0, flags, 1UL << ConstantPoolCacheEntry::is_vfinal_shift); + __ beqz(t0, notFinal); + + const Register method = index; // method must be xmethod + assert(method == xmethod, "Method must be xmethod for interpreter calling convention"); + + // do the call - the index is actually the method to call + // that is, f2 is a vtable index if !is_vfinal, else f2 is a Method* + + // It's final, need a null check here! + __ null_check(recv); + + // profile this call + __ profile_final_call(x10); + __ profile_arguments_type(x10, method, x14, true); + + __ jump_from_interpreted(method); + + __ bind(notFinal); + + // get receiver klass + __ null_check(recv, oopDesc::klass_offset_in_bytes()); + __ load_klass(x10, recv); + + // profile this call + __ profile_virtual_call(x10, xlocals, x13); + + // get target Method & entry point + __ lookup_virtual_method(x10, index, method); + __ profile_arguments_type(x13, method, x14, true); + __ jump_from_interpreted(method); +} + +void TemplateTable::invokevirtual(int byte_no) +{ + transition(vtos, vtos); + assert(byte_no == f2_byte, "use this argument"); + + prepare_invoke(byte_no, xmethod, noreg, x12, x13); + + // xmethod: index (actually a Method*) + // x12: receiver + // x13: flags + + invokevirtual_helper(xmethod, x12, x13); +} + +void TemplateTable::invokespecial(int byte_no) +{ + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + + prepare_invoke(byte_no, xmethod, noreg, // get f1 Method* + x12); // get receiver also for null check + __ verify_oop(x12); + __ null_check(x12); + // do the call + __ profile_call(x10); + __ profile_arguments_type(x10, xmethod, xbcp, false); + __ jump_from_interpreted(xmethod); +} + +void TemplateTable::invokestatic(int byte_no) +{ + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this arugment"); + + prepare_invoke(byte_no, xmethod); // get f1 Method* + // do the call + __ profile_call(x10); + __ profile_arguments_type(x10, xmethod, x14, false); + __ jump_from_interpreted(xmethod); +} + +void TemplateTable::fast_invokevfinal(int byte_no) +{ + __ call_Unimplemented(); +} + +void TemplateTable::invokeinterface(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + + prepare_invoke(byte_no, x10, xmethod, // get f1 Klass*, f2 Method* + x12, x13); // recv, flags + + // x10: interface klass (from f1) + // xmethod: method (from f2) + // x12: receiver + // x13: flags + + // First check for Object case, then private interface method, + // then regular interface method. + + // Special case of invokeinterface called for virtual method of + // java.lang.Object. See cpCache.cpp for details + Label notObjectMethod; + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_forced_virtual_shift); + __ beqz(t0, notObjectMethod); + + invokevirtual_helper(xmethod, x12, x13); + __ bind(notObjectMethod); + + Label no_such_interface; + + // Check for private method invocation - indicated by vfinal + Label notVFinal; + __ andi(t0, x13, 1UL << ConstantPoolCacheEntry::is_vfinal_shift); + __ beqz(t0, notVFinal); + + // Check receiver klass into x13 - also a null check + __ null_check(x12, oopDesc::klass_offset_in_bytes()); + __ load_klass(x13, x12); + + Label subtype; + __ check_klass_subtype(x13, x10, x14, subtype); + // If we get here the typecheck failed + __ j(no_such_interface); + __ bind(subtype); + + __ profile_final_call(x10); + __ profile_arguments_type(x10, xmethod, x14, true); + __ jump_from_interpreted(xmethod); + + __ bind(notVFinal); + + // Get receiver klass into x13 - also a null check + __ restore_locals(); + __ null_check(x12, oopDesc::klass_offset_in_bytes()); + __ load_klass(x13, x12); + + Label no_such_method; + + // Preserve method for the throw_AbstractMethodErrorVerbose. + __ mv(x28, xmethod); + // Receiver subtype check against REFC. + // Superklass in x10. Subklass in x13. Blows t1, x30 + __ lookup_interface_method(// inputs: rec. class, interface, itable index + x13, x10, noreg, + // outputs: scan temp. reg, scan temp. reg + t1, x30, + no_such_interface, + /*return_method=*/false); + + // profile this call + __ profile_virtual_call(x13, x30, x9); + + // Get declaring interface class from method, and itable index + __ load_method_holder(x10, xmethod); + __ lwu(xmethod, Address(xmethod, Method::itable_index_offset())); + __ subw(xmethod, xmethod, Method::itable_index_max); + __ negw(xmethod, xmethod); + + // Preserve recvKlass for throw_AbstractMethodErrorVerbose + __ mv(xlocals, x13); + __ lookup_interface_method(// inputs: rec. class, interface, itable index + xlocals, x10, xmethod, + // outputs: method, scan temp. reg + xmethod, x30, + no_such_interface); + + // xmethod: Method to call + // x12: receiver + // Check for abstract method error + // Note: This should be done more efficiently via a throw_abstract_method_error + // interpreter entry point and a conditional jump to it in case of a null + // method. + __ beqz(xmethod, no_such_method); + + __ profile_arguments_type(x13, xmethod, x30, true); + + // do the call + // x12: receiver + // xmethod: Method + __ jump_from_interpreted(xmethod); + __ should_not_reach_here(); + + // exception handling code follows ... + // note: must restore interpreter registers to canonical + // state for exception handling to work correctly! + + __ bind(no_such_method); + // throw exception + __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) + // Pass arguments for generating a verbose error message. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose), x13, x28); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + + __ bind(no_such_interface); + // throw exceptiong + __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) + // Pass arguments for generating a verbose error message. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose), x13, x10); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + return; +} + +void TemplateTable::invokehandle(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + + prepare_invoke(byte_no, xmethod, x10, x12); + __ verify_method_ptr(x12); + __ verify_oop(x12); + __ null_check(x12); + + // FIXME: profile the LambdaForm also + + // x30 is safe to use here as a temp reg because it is about to + // be clobbered by jump_from_interpreted(). + __ profile_final_call(x30); + __ profile_arguments_type(x30, xmethod, x14, true); + + __ jump_from_interpreted(xmethod); +} + +void TemplateTable::invokedynamic(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + + prepare_invoke(byte_no, xmethod, x10); + + // x10: CallSite object (from cpool->resolved_references[]) + // xmethod: MH.linkToCallSite method (from f2) + + // Note: x10_callsite is already pushed by prepare_invoke + + // %%% should make a type profile for any invokedynamic that takes a ref argument + // profile this call + __ profile_call(xbcp); + __ profile_arguments_type(x13, xmethod, x30, false); + + __ verify_oop(x10); + + __ jump_from_interpreted(xmethod); +} + +//----------------------------------------------------------------------------- +// Allocation + +void TemplateTable::_new() { + transition(vtos, atos); + + __ get_unsigned_2_byte_index_at_bcp(x13, 1); + Label slow_case; + Label done; + Label initialize_header; + Label initialize_object; // including clearing the fields + + __ get_cpool_and_tags(x14, x10); + // Make sure the class we're about to instantiate has been resolved. + // This is done before loading InstanceKlass to be consistent with the order + // how Constant Pool is update (see ConstantPool::klass_at_put) + const int tags_offset = Array::base_offset_in_bytes(); + __ add(t0, x10, x13); + __ la(t0, Address(t0, tags_offset)); + __ membar(MacroAssembler::AnyAny); + __ lbu(t0, t0); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ sub(t1, t0, (u1)JVM_CONSTANT_Class); + __ bnez(t1, slow_case); + + // get InstanceKlass + __ load_resolved_klass_at_offset(x14, x13, x14, t0); + + // make sure klass is initialized & doesn't have finalizer + // make sure klass is fully initialized + __ lbu(t0, Address(x14, InstanceKlass::init_state_offset())); + __ sub(t1, t0, (u1)InstanceKlass::fully_initialized); + __ bnez(t1, slow_case); + + // get instance_size in InstanceKlass (scaled to a count of bytes) + __ lwu(x13, Address(x14, Klass::layout_helper_offset())); + // test to see if it has a finalizer or is malformed in some way + __ andi(t0, x13, Klass::_lh_instance_slow_path_bit); + __ bnez(t0, slow_case); + + // Allocate the instance: + // If TLAB is enabled: + // Try to allocate in the TLAB. + // If fails, go to the slow path. + // Else If inline contiguous allocations are enabled: + // Try to allocate in eden. + // If fails due to heap end, go to slow path + // + // If TLAB is enabled OR inline contiguous is enabled: + // Initialize the allocation. + // Exit. + // Go to slow path. + const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc(); + + if (UseTLAB) { + __ tlab_allocate(x10, x13, 0, noreg, x11, slow_case); + + if (ZeroTLAB) { + // the fields have been already cleared + __ j(initialize_header); + } else { + // initialize both the header and fields + __ j(initialize_object); + } + } else { + // Allocation in the shared Eden, if allowed. + // + // x13: instance size in bytes + if (allow_shared_alloc) { + __ eden_allocate(x10, x13, 0, x28, slow_case); + } + } + + // If USETLAB or allow_shared_alloc are true, the object is created above and + // there is an initialized need. Otherwise, skip and go to the slow path. + if (UseTLAB || allow_shared_alloc) { + // The object is initialized before the header. If the object size is + // zero, go directly to the header initialization. + __ bind(initialize_object); + __ sub(x13, x13, sizeof(oopDesc)); + __ beqz(x13, initialize_header); + + // Initialize obejct fields + { + __ add(x12, x10, sizeof(oopDesc)); + Label loop; + __ bind(loop); + __ sd(zr, Address(x12)); + __ add(x12, x12, BytesPerLong); + __ sub(x13, x13, BytesPerLong); + __ bnez(x13, loop); + } + + // initialize object hader only. + __ bind(initialize_header); + __ mv(t0, (intptr_t)markWord::prototype().value()); + __ sd(t0, Address(x10, oopDesc::mark_offset_in_bytes())); + __ store_klass_gap(x10, zr); // zero klass gap for compressed oops + __ store_klass(x10, x14); // store klass last + + { + SkipIfEqual skip(_masm, &DTraceAllocProbes, false); + // Trigger dtrace event for fastpath + __ push(atos); // save the return value + __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), x10); + __ pop(atos); // restore the return value + } + __ j(done); + } + + // slow case + __ bind(slow_case); + __ get_constant_pool(c_rarg1); + __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), c_rarg1, c_rarg2); + __ verify_oop(x10); + + // continue + __ bind(done); + // Must prevent reordering of stores for object initialization with stores that publish the new object. + __ membar(MacroAssembler::StoreStore); +} + +void TemplateTable::newarray() { + transition(itos, atos); + __ load_unsigned_byte(c_rarg1, at_bcp(1)); + __ mv(c_rarg2, x10); + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), + c_rarg1, c_rarg2); + // Must prevent reordering of stores for object initialization with stores that publish the new object. + __ membar(MacroAssembler::StoreStore); +} + +void TemplateTable::anewarray() { + transition(itos, atos); + __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); + __ get_constant_pool(c_rarg1); + __ mv(c_rarg3, x10); + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), + c_rarg1, c_rarg2, c_rarg3); + // Must prevent reordering of stores for object initialization with stores that publish the new object. + __ membar(MacroAssembler::StoreStore); +} + +void TemplateTable::arraylength() { + transition(atos, itos); + __ null_check(x10, arrayOopDesc::length_offset_in_bytes()); + __ lwu(x10, Address(x10, arrayOopDesc::length_offset_in_bytes())); +} + +void TemplateTable::checkcast() +{ + transition(atos, atos); + Label done, is_null, ok_is_subtype, quicked, resolved; + __ beqz(x10, is_null); + + // Get cpool & tags index + __ get_cpool_and_tags(x12, x13); // x12=cpool, x13=tags array + __ get_unsigned_2_byte_index_at_bcp(x9, 1); // x9=index + // See if bytecode has already been quicked + __ add(t0, x13, Array::base_offset_in_bytes()); + __ add(x11, t0, x9); + __ membar(MacroAssembler::AnyAny); + __ lbu(x11, x11); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ sub(t0, x11, (u1)JVM_CONSTANT_Class); + __ beqz(t0, quicked); + + __ push(atos); // save receiver for result, and for GC + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); + // vm_result_2 has metadata result + __ get_vm_result_2(x10, xthread); + __ pop_reg(x13); // restore receiver + __ j(resolved); + + // Get superklass in x10 and subklass in x13 + __ bind(quicked); + __ mv(x13, x10); // Save object in x13; x10 needed for subtype check + __ load_resolved_klass_at_offset(x12, x9, x10, t0); // x10 = klass + + __ bind(resolved); + __ load_klass(x9, x13); + + // Generate subtype check. Blows x12, x15. Object in x13. + // Superklass in x10. Subklass in x9. + __ gen_subtype_check(x9, ok_is_subtype); + + // Come here on failure + __ push_reg(x13); + // object is at TOS + __ j(Interpreter::_throw_ClassCastException_entry); + + // Come here on success + __ bind(ok_is_subtype); + __ mv(x10, x13); // Restore object in x13 + + // Collect counts on whether this test sees NULLs a lot or not. + if (ProfileInterpreter) { + __ j(done); + __ bind(is_null); + __ profile_null_seen(x12); + } else { + __ bind(is_null); // same as 'done' + } + __ bind(done); +} + +void TemplateTable::instanceof() { + transition(atos, itos); + Label done, is_null, ok_is_subtype, quicked, resolved; + __ beqz(x10, is_null); + + // Get cpool & tags index + __ get_cpool_and_tags(x12, x13); // x12=cpool, x13=tags array + __ get_unsigned_2_byte_index_at_bcp(x9, 1); // x9=index + // See if bytecode has already been quicked + __ add(t0, x13, Array::base_offset_in_bytes()); + __ add(x11, t0, x9); + __ membar(MacroAssembler::AnyAny); + __ lbu(x11, x11); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ sub(t0, x11, (u1)JVM_CONSTANT_Class); + __ beqz(t0, quicked); + + __ push(atos); // save receiver for result, and for GC + call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); + // vm_result_2 has metadata result + __ get_vm_result_2(x10, xthread); + __ pop_reg(x13); // restore receiver + __ verify_oop(x13); + __ load_klass(x13, x13); + __ j(resolved); + + // Get superklass in x10 and subklass in x13 + __ bind(quicked); + __ load_klass(x13, x10); + __ load_resolved_klass_at_offset(x12, x9, x10, t0); + + __ bind(resolved); + + // Generate subtype check. Blows x12, x15 + // Superklass in x10. Subklass in x13. + __ gen_subtype_check(x13, ok_is_subtype); + + // Come here on failure + __ mv(x10, zr); + __ j(done); + // Come here on success + __ bind(ok_is_subtype); + __ li(x10, 1); + + // Collect counts on whether this test sees NULLs a lot or not. + if (ProfileInterpreter) { + __ j(done); + __ bind(is_null); + __ profile_null_seen(x12); + } else { + __ bind(is_null); // same as 'done' + } + __ bind(done); + // x10 = 0: obj == NULL or obj is not an instanceof the specified klass + // x10 = 1: obj != NULL and obj is an instanceof the specified klass +} + +//----------------------------------------------------------------------------- +// Breakpoints +void TemplateTable::_breakpoint() { + // Note: We get here even if we are single stepping.. + // jbug inists on setting breakpoints at every bytecode + // even if we are in single step mode. + + transition(vtos, vtos); + + // get the unpatched byte code + __ get_method(c_rarg1); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::get_original_bytecode_at), + c_rarg1, xbcp); + __ mv(x9, x10); + + // post the breakpoint event + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), + xmethod, xbcp); + + // complete the execution of original bytecode + __ mv(t0, x9); + __ dispatch_only_normal(vtos); +} + +//----------------------------------------------------------------------------- +// Exceptions + +void TemplateTable::athrow() { + transition(atos, vtos); + __ null_check(x10); + __ j(Interpreter::throw_exception_entry()); +} + +//----------------------------------------------------------------------------- +// Synchronization +// +// Note: monitorenter & exit are symmetric routines; which is reflected +// in the assembly code structure as well +// +// Stack layout: +// +// [expressions ] <--- esp = expression stack top +// .. +// [expressions ] +// [monitor entry] <--- monitor block top = expression stack bot +// .. +// [monitor entry] +// [frame data ] <--- monitor block bot +// ... +// [saved fp ] <--- fp +void TemplateTable::monitorenter() +{ + transition(atos, vtos); + + // check for NULL object + __ null_check(x10); + + const Address monitor_block_top( + fp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const Address monitor_block_bot( + fp, frame::interpreter_frame_initial_sp_offset * wordSize); + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + + Label allocated; + + // initialize entry pointer + __ mv(c_rarg1, zr); // points to free slot or NULL + + // find a free slot in the monitor block (result in c_rarg1) + { + Label entry, loop, exit, notUsed; + __ ld(c_rarg3, monitor_block_top); // points to current entry, + // starting with top-most entry + __ la(c_rarg2, monitor_block_bot); // points to word before bottom + + __ j(entry); + + __ bind(loop); + // check if current entry is used + // if not used then remember entry in c_rarg1 + __ ld(t0, Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes())); + __ bnez(t0, notUsed); + __ mv(c_rarg1, c_rarg3); + __ bind(notUsed); + // check if current entry is for same object + // if same object then stop searching + __ beq(x10, t0, exit); + // otherwise advance to next entry + __ add(c_rarg3, c_rarg3, entry_size); + __ bind(entry); + // check if bottom reached + // if not at bottom then check this entry + __ bne(c_rarg3, c_rarg2, loop); + __ bind(exit); + } + + __ bnez(c_rarg1, allocated); // check if a slot has been found and + // if found, continue with that on + + // allocate one if there's no free slot + { + Label entry, loop; + // 1. compute new pointers // esp: old expression stack top + __ ld(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom + __ sub(esp, esp, entry_size); // move expression stack top + __ sub(c_rarg1, c_rarg1, entry_size); // move expression stack bottom + __ mv(c_rarg3, esp); // set start value for copy loop + __ sd(c_rarg1, monitor_block_bot); // set new monitor block bottom + __ sub(sp, sp, entry_size); // make room for the monitor + + __ j(entry); + // 2. move expression stack contents + __ bind(loop); + __ ld(c_rarg2, Address(c_rarg3, entry_size)); // load expression stack + // word from old location + __ sd(c_rarg2, Address(c_rarg3, 0)); // and store it at new location + __ add(c_rarg3, c_rarg3, wordSize); // advance to next word + __ bind(entry); + __ bne(c_rarg3, c_rarg1, loop); // check if bottom reached.if not at bottom + // then copy next word + } + + // call run-time routine + // c_rarg1: points to monitor entry + __ bind(allocated); + + // Increment bcp to point to the next bytecode, so exception + // handling for async. exceptions work correctly. + // The object has already been poped from the stack, so the + // expression stack looks correct. + __ addi(xbcp, xbcp, 1); + + // store object + __ sd(x10, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); + __ lock_object(c_rarg1); + + // check to make sure this monitor doesn't cause stack overflow after locking + __ save_bcp(); // in case of exception + __ generate_stack_overflow_check(0); + + // The bcp has already been incremented. Just need to dispatch to + // next instruction. + __ dispatch_next(vtos); +} + +void TemplateTable::monitorexit() +{ + transition(atos, vtos); + + // check for NULL object + __ null_check(x10); + + const Address monitor_block_top( + fp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const Address monitor_block_bot( + fp, frame::interpreter_frame_initial_sp_offset * wordSize); + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + + Label found; + + // find matching slot + { + Label entry, loop; + __ ld(c_rarg1, monitor_block_top); // points to current entry, + // starting with top-most entry + __ la(c_rarg2, monitor_block_bot); // points to word before bottom + // of monitor block + __ j(entry); + + __ bind(loop); + // check if current entry is for same object + __ ld(t0, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); + // if same object then stop searching + __ beq(x10, t0, found); + // otherwise advance to next entry + __ add(c_rarg1, c_rarg1, entry_size); + __ bind(entry); + // check if bottom reached + // if not at bottom then check this entry + __ bne(c_rarg1, c_rarg2, loop); + } + + // error handling. Unlocking was not block-structured + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_illegal_monitor_state_exception)); + __ should_not_reach_here(); + + // call run-time routine + __ bind(found); + __ push_ptr(x10); // make sure object is on stack (contract with oopMaps) + __ unlock_object(c_rarg1); + __ pop_ptr(x10); // discard object +} + +// Wide instructions +void TemplateTable::wide() +{ + __ load_unsigned_byte(x9, at_bcp(1)); + __ mv(t0, (address)Interpreter::_wentry_point); + __ shadd(t0, x9, t0, t1, 3); + __ ld(t0, Address(t0)); + __ jr(t0); +} + +// Multi arrays +void TemplateTable::multianewarray() { + transition(vtos, atos); + __ load_unsigned_byte(x10, at_bcp(3)); // get number of dimensions + // last dim is on top of stack; we want address of first one: + // first_addr = last_addr + (ndims - 1) * wordSize + __ shadd(c_rarg1, x10, esp, c_rarg1, 3); + __ sub(c_rarg1, c_rarg1, wordSize); + call_VM(x10, + CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), + c_rarg1); + __ load_unsigned_byte(x11, at_bcp(3)); + __ shadd(esp, x11, esp, t0, 3); +} diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.hpp b/src/hotspot/cpu/riscv/templateTable_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fcc86108d2839da91af45bb312fc8fdb27116125 --- /dev/null +++ b/src/hotspot/cpu/riscv/templateTable_riscv.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_TEMPLATETABLE_RISCV_HPP +#define CPU_RISCV_TEMPLATETABLE_RISCV_HPP + +static void prepare_invoke(int byte_no, + Register method, // linked method (or i-klass) + Register index = noreg, // itable index, MethodType, etc. + Register recv = noreg, // if caller wants to see it + Register flags = noreg // if caller wants to test it + ); +static void invokevirtual_helper(Register index, Register recv, + Register flags); + +// Helpers +static void index_check(Register array, Register index); + +#endif // CPU_RISCV_TEMPLATETABLE_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp b/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f50adb05c3155babdd3a96e32e6b9784e8ac694 --- /dev/null +++ b/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "prims/universalNativeInvoker.hpp" +#include "utilities/debug.hpp" + +address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) { + Unimplemented(); + return nullptr; +} diff --git a/src/java.base/unix/native/libnet/InetAddressImplFactory.c b/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp similarity index 56% rename from src/java.base/unix/native/libnet/InetAddressImplFactory.c rename to src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp index 2c799feb105dcf88ee78d2cdfb8493273c9b7817..ce70da72f2e468b52c5275d004eeb84212d4b90c 100644 --- a/src/java.base/unix/native/libnet/InetAddressImplFactory.c +++ b/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp @@ -1,12 +1,11 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -21,26 +20,23 @@ * Please 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 "java_net_InetAddressImplFactory.h" +#include "precompiled.hpp" +#include "prims/universalUpcallHandler.hpp" +#include "utilities/debug.hpp" -#include "net_util.h" +address ProgrammableUpcallHandler::generate_upcall_stub(jobject jrec, jobject jabi, jobject jlayout) { + Unimplemented(); + return nullptr; +} -/************************************************************************ - * InetAddressImplFactory - */ +address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject mh, Method* entry, jobject jabi, jobject jconv) { + ShouldNotCallThis(); + return nullptr; +} -/* - * Class: java_net_InetAddressImplFactory - * Method: isIPv6Supported - * Signature: ()I - */ -JNIEXPORT jboolean JNICALL -Java_java_net_InetAddressImplFactory_isIPv6Supported(JNIEnv *env, jclass cls) { - if (ipv6_available()) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } +bool ProgrammableUpcallHandler::supports_optimized_upcalls() { + return false; } diff --git a/src/hotspot/cpu/riscv/vmStructs_riscv.hpp b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6c89133de02800c38da1476eb9e44f4fe2603049 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_VMSTRUCTS_RISCV_HPP +#define CPU_RISCV_VMSTRUCTS_RISCV_HPP + +// These are the CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#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) \ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) + +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) + +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // CPU_RISCV_VMSTRUCTS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..559f8b5e4ea242666348b9e79d3c887edf9bbe10 --- /dev/null +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/java.hpp" +#include "runtime/os.hpp" +#include "runtime/vm_version.hpp" +#include "utilities/formatBuffer.hpp" +#include "utilities/macros.hpp" + +#include OS_HEADER_INLINE(os) + +const char* VM_Version::_uarch = ""; +uint32_t VM_Version::_initial_vector_length = 0; + +void VM_Version::initialize() { + get_os_cpu_info(); + + if (FLAG_IS_DEFAULT(UseFMA)) { + FLAG_SET_DEFAULT(UseFMA, true); + } + + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0); + } + + if (UseAES || UseAESIntrinsics) { + if (UseAES && !FLAG_IS_DEFAULT(UseAES)) { + warning("AES instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseAES, false); + } + if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) { + warning("AES intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseAESIntrinsics, false); + } + } + + if (UseAESCTRIntrinsics) { + warning("AES/CTR intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); + } + + if (UseSHA) { + warning("SHA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseSHA, false); + } + + if (UseSHA1Intrinsics) { + warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + } + + if (UseSHA256Intrinsics) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); + } + + if (UseSHA512Intrinsics) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + + if (UseSHA3Intrinsics) { + warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); + } + + if (UseCRC32Intrinsics) { + warning("CRC32 intrinsics are not available on this CPU."); + FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); + } + + if (UseCRC32CIntrinsics) { + warning("CRC32C intrinsics are not available on this CPU."); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + + if (UseMD5Intrinsics) { + warning("MD5 intrinsics are not available on this CPU."); + FLAG_SET_DEFAULT(UseMD5Intrinsics, false); + } + + if (UseRVV) { + if (!(_features & CPU_V)) { + warning("RVV is not supported on this CPU"); + FLAG_SET_DEFAULT(UseRVV, false); + } else { + // read vector length from vector CSR vlenb + _initial_vector_length = get_current_vector_length(); + } + } + + if (UseRVC && !(_features & CPU_C)) { + warning("RVC is not supported on this CPU"); + FLAG_SET_DEFAULT(UseRVC, false); + } + + if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) { + FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true); + } + + if (UseZbb) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_DEFAULT(UsePopCountInstruction, true); + } + } else { + FLAG_SET_DEFAULT(UsePopCountInstruction, false); + } + + char buf[512]; + buf[0] = '\0'; + if (_uarch != NULL && strcmp(_uarch, "") != 0) snprintf(buf, sizeof(buf), "%s,", _uarch); + strcat(buf, "rv64"); +#define ADD_FEATURE_IF_SUPPORTED(id, name, bit) if (_features & CPU_##id) strcat(buf, name); + CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED) +#undef ADD_FEATURE_IF_SUPPORTED + + _features_string = os::strdup(buf); + +#ifdef COMPILER2 + c2_initialize(); +#endif // COMPILER2 +} + +#ifdef COMPILER2 +void VM_Version::c2_initialize() { + if (UseCMoveUnconditionally) { + FLAG_SET_DEFAULT(UseCMoveUnconditionally, false); + } + + if (ConditionalMoveLimit > 0) { + FLAG_SET_DEFAULT(ConditionalMoveLimit, 0); + } + + if (!UseRVV) { + FLAG_SET_DEFAULT(SpecialEncodeISOArray, false); + } + + if (!UseRVV && MaxVectorSize) { + FLAG_SET_DEFAULT(MaxVectorSize, 0); + } + + if (!UseRVV) { + FLAG_SET_DEFAULT(UseRVVForBigIntegerShiftIntrinsics, false); + } + + if (UseRVV) { + if (FLAG_IS_DEFAULT(MaxVectorSize)) { + MaxVectorSize = _initial_vector_length; + } else if (MaxVectorSize < 16) { + warning("RVV does not support vector length less than 16 bytes. Disabling RVV."); + UseRVV = false; + } else if (is_power_of_2(MaxVectorSize)) { + if (MaxVectorSize > _initial_vector_length) { + warning("Current system only supports max RVV vector length %d. Set MaxVectorSize to %d", + _initial_vector_length, _initial_vector_length); + } + MaxVectorSize = _initial_vector_length; + } else { + vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize)); + } + } + + // disable prefetch + if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); + } + + if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + FLAG_SET_DEFAULT(UseMulAddIntrinsic, true); + } + + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); + } + + if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true); + } + + if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); + } + + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); + } +} +#endif // COMPILER2 + +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64"); + snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string); + _initialized = true; +} diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1d6eeb97504c94673cc19392ea25f47aebed6240 --- /dev/null +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_VM_VERSION_RISCV_HPP +#define CPU_RISCV_VM_VERSION_RISCV_HPP + +#include "runtime/abstract_vm_version.hpp" +#include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" +#include "utilities/sizes.hpp" + +class VM_Version : public Abstract_VM_Version { +#ifdef COMPILER2 +private: + static void c2_initialize(); +#endif // COMPILER2 + +protected: + static const char* _uarch; + static uint32_t _initial_vector_length; + static void get_os_cpu_info(); + static uint32_t get_current_vector_length(); + +public: + // Initialization + static void initialize(); + + constexpr static bool supports_stack_watermark_barrier() { return true; } + + enum Feature_Flag { +#define CPU_FEATURE_FLAGS(decl) \ + decl(I, "i", 8) \ + decl(M, "m", 12) \ + decl(A, "a", 0) \ + decl(F, "f", 5) \ + decl(D, "d", 3) \ + decl(C, "c", 2) \ + decl(V, "v", 21) + +#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit), + CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) +#undef DECLARE_CPU_FEATURE_FLAG + }; + + static void initialize_cpu_information(void); +}; + +#endif // CPU_RISCV_VM_VERSION_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.cpp b/src/hotspot/cpu/riscv/vmreg_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa7222dc64a477f90f549bf10d52c1a7f762b568 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "code/vmreg.hpp" + +void VMRegImpl::set_regName() { + int i = 0; + Register reg = ::as_Register(0); + for ( ; i < ConcreteRegisterImpl::max_gpr ; ) { + for (int j = 0 ; j < RegisterImpl::max_slots_per_register ; j++) { + regName[i++] = reg->name(); + } + reg = reg->successor(); + } + + FloatRegister freg = ::as_FloatRegister(0); + for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { + for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { + regName[i++] = reg->name(); + } + freg = freg->successor(); + } + + VectorRegister vreg = ::as_VectorRegister(0); + for ( ; i < ConcreteRegisterImpl::max_vpr ; ) { + for (int j = 0 ; j < VectorRegisterImpl::max_slots_per_register ; j++) { + regName[i++] = reg->name(); + } + vreg = vreg->successor(); + } + + for ( ; i < ConcreteRegisterImpl::number_of_registers ; i++) { + regName[i] = "NON-GPR-FPR-VPR"; + } +} + +VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { + Unimplemented(); + return VMRegImpl::Bad(); +} diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.hpp b/src/hotspot/cpu/riscv/vmreg_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9e611b1f67110b05b8f0a7db6447d0d59510e2d7 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_VMREG_RISCV_HPP +#define CPU_RISCV_VMREG_RISCV_HPP + +inline bool is_Register() { + return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; +} + +inline bool is_FloatRegister() { + return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; +} + +inline bool is_VectorRegister() { + return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_vpr; +} + +inline Register as_Register() { + assert(is_Register(), "must be"); + return ::as_Register(value() / RegisterImpl::max_slots_per_register); +} + +inline FloatRegister as_FloatRegister() { + assert(is_FloatRegister() && is_even(value()), "must be"); + return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / + FloatRegisterImpl::max_slots_per_register); +} + +inline VectorRegister as_VectorRegister() { + assert(is_VectorRegister() && ((value() & (VectorRegisterImpl::max_slots_per_register - 1)) == 0), "must be"); + return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) / + VectorRegisterImpl::max_slots_per_register); +} + +inline bool is_concrete() { + assert(is_reg(), "must be"); + if (is_VectorRegister()) { + int base = value() - ConcreteRegisterImpl::max_fpr; + return (base % VectorRegisterImpl::max_slots_per_register) == 0; + } else { + return is_even(value()); + } +} + +#endif // CPU_RISCV_VMREG_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp b/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..06b70020b4b98170e89e291d33c465715894c112 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_RISCV_VM_VMREG_RISCV_INLINE_HPP +#define CPU_RISCV_VM_VMREG_RISCV_INLINE_HPP + +inline VMReg RegisterImpl::as_VMReg() const { + if (this == noreg) { + return VMRegImpl::Bad(); + } + return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register); +} + +inline VMReg FloatRegisterImpl::as_VMReg() const { + return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) + + ConcreteRegisterImpl::max_gpr); +} + +inline VMReg VectorRegisterImpl::as_VMReg() const { + return VMRegImpl::as_VMReg((encoding() * VectorRegisterImpl::max_slots_per_register) + + ConcreteRegisterImpl::max_fpr); +} + +#endif // CPU_RISCV_VM_VMREG_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78b81138003f6c37698df683a8ef9c1b6779c08f --- /dev/null +++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/macroAssembler.inline.hpp" +#include "assembler_riscv.inline.hpp" +#include "code/vtableStubs.hpp" +#include "interp_masm_riscv.hpp" +#include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klassVtable.hpp" +#include "runtime/sharedRuntime.hpp" +#include "vmreg_riscv.inline.hpp" +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +// machine-dependent part of VtableStubs: create VtableStub of correct size and +// initialize its code + +#define __ masm-> + +#ifndef PRODUCT +extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); +#endif + +VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { + // Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing. + const int stub_code_length = code_size_limit(true); + VtableStub* s = new(stub_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + + // Count unused bytes in instruction sequences of variable size. + // We add them to the computed buffer size in order to avoid + // overflow in subsequently generated stubs. + address start_pc = NULL; + int slop_bytes = 0; + int slop_delta = 0; + + ResourceMark rm; + CodeBuffer cb(s->entry_point(), stub_code_length); + MacroAssembler* masm = new MacroAssembler(&cb); + assert_cond(masm != NULL); + +#if (!defined(PRODUCT) && defined(COMPILER2)) + if (CountCompiledCalls) { + __ la(t2, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); + __ add_memory_int64(Address(t2), 1); + } +#endif + + // get receiver (need to skip return address on top of stack) + assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); + + // get receiver klass + address npe_addr = __ pc(); + __ load_klass(t2, j_rarg0); + +#ifndef PRODUCT + if (DebugVtables) { + Label L; + start_pc = __ pc(); + + // check offset vs vtable length + __ lwu(t0, Address(t2, Klass::vtable_length_offset())); + __ mvw(t1, vtable_index * vtableEntry::size()); + __ bgt(t0, t1, L); + __ enter(); + __ mv(x12, vtable_index); + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), j_rarg0, x12); + const ptrdiff_t estimate = 256; + const ptrdiff_t codesize = __ pc() - start_pc; + slop_delta = estimate - codesize; // call_VM varies in length, depending on data + slop_bytes += slop_delta; + assert(slop_delta >= 0, "vtable #%d: Code size estimate (%d) for DebugVtables too small, required: %d", vtable_index, (int)estimate, (int)codesize); + + __ leave(); + __ bind(L); + } +#endif // PRODUCT + + start_pc = __ pc(); + __ lookup_virtual_method(t2, vtable_index, xmethod); + // lookup_virtual_method generates + // 4 instructions (maximum value encountered in normal case):li(lui + addiw) + add + ld + // 1 instruction (best case):ld * 1 + slop_delta = 16 - (int)(__ pc() - start_pc); + slop_bytes += slop_delta; + assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta); + +#ifndef PRODUCT + if (DebugVtables) { + Label L; + __ beqz(xmethod, L); + __ ld(t0, Address(xmethod, Method::from_compiled_offset())); + __ bnez(t0, L); + __ stop("Vtable entry is NULL"); + __ bind(L); + } +#endif // PRODUCT + + // x10: receiver klass + // xmethod: Method* + // x12: receiver + address ame_addr = __ pc(); + __ ld(t0, Address(xmethod, Method::from_compiled_offset())); + __ jr(t0); + + masm->flush(); + bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); + + return s; +} + +VtableStub* VtableStubs::create_itable_stub(int itable_index) { + // Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing. + const int stub_code_length = code_size_limit(false); + VtableStub* s = new(stub_code_length) VtableStub(false, itable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + // Count unused bytes in instruction sequences of variable size. + // We add them to the computed buffer size in order to avoid + // overflow in subsequently generated stubs. + address start_pc = NULL; + int slop_bytes = 0; + int slop_delta = 0; + + ResourceMark rm; + CodeBuffer cb(s->entry_point(), stub_code_length); + MacroAssembler* masm = new MacroAssembler(&cb); + assert_cond(masm != NULL); + +#if (!defined(PRODUCT) && defined(COMPILER2)) + if (CountCompiledCalls) { + __ la(x18, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); + __ add_memory_int64(Address(x18), 1); + } +#endif + + // get receiver (need to skip return address on top of stack) + assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); + + // Entry arguments: + // t2: CompiledICHolder + // j_rarg0: Receiver + + // This stub is called from compiled code which has no callee-saved registers, + // so all registers except arguments are free at this point. + const Register recv_klass_reg = x18; + const Register holder_klass_reg = x19; // declaring interface klass (DECC) + const Register resolved_klass_reg = xmethod; // resolved interface klass (REFC) + const Register temp_reg = x28; + const Register temp_reg2 = x29; + const Register icholder_reg = t1; + + Label L_no_such_interface; + + __ ld(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); + __ ld(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + + start_pc = __ pc(); + + // get receiver klass (also an implicit null-check) + address npe_addr = __ pc(); + __ load_klass(recv_klass_reg, j_rarg0); + + // Receiver subtype check against REFC. + __ lookup_interface_method(// inputs: rec. class, interface + recv_klass_reg, resolved_klass_reg, noreg, + // outputs: scan temp. reg1, scan temp. reg2 + temp_reg2, temp_reg, + L_no_such_interface, + /*return_method=*/false); + + const ptrdiff_t typecheckSize = __ pc() - start_pc; + start_pc = __ pc(); + + // Get selected method from declaring class and itable index + __ lookup_interface_method(// inputs: rec. class, interface, itable index + recv_klass_reg, holder_klass_reg, itable_index, + // outputs: method, scan temp. reg + xmethod, temp_reg, + L_no_such_interface); + + const ptrdiff_t lookupSize = __ pc() - start_pc; + + // Reduce "estimate" such that "padding" does not drop below 8. + const ptrdiff_t estimate = 256; + const ptrdiff_t codesize = typecheckSize + lookupSize; + slop_delta = (int)(estimate - codesize); + slop_bytes += slop_delta; + assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize); + +#ifdef ASSERT + if (DebugVtables) { + Label L2; + __ beqz(xmethod, L2); + __ ld(t0, Address(xmethod, Method::from_compiled_offset())); + __ bnez(t0, L2); + __ stop("compiler entrypoint is null"); + __ bind(L2); + } +#endif // ASSERT + + // xmethod: Method* + // j_rarg0: receiver + address ame_addr = __ pc(); + __ ld(t0, Address(xmethod, Method::from_compiled_offset())); + __ jr(t0); + + __ bind(L_no_such_interface); + // Handle IncompatibleClassChangeError in itable stubs. + // More detailed error message. + // We force resolving of the call site by jumping to the "handle + // wrong method" stub, and so let the interpreter runtime do all the + // dirty work. + assert(SharedRuntime::get_handle_wrong_method_stub() != NULL, "check initialization order"); + __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); + + masm->flush(); + bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); + + return s; +} + +int VtableStub::pd_code_alignment() { + // RISCV cache line size is not an architected constant. We just align on word size. + const unsigned int icache_line_size = wordSize; + return icache_line_size; +} diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index 1d64ceebeb03b4013898396bb0eac9c1ce922f06..7a1c31157b0d55645f511019e365d149d7fc991a 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2021 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -729,6 +729,7 @@ class Assembler : public AbstractAssembler { #define SLRK_ZOPC (unsigned int)(0xb9 << 24 | 0x00fb << 16) #define SLGRK_ZOPC (unsigned int)(0xb9 << 24 | 0x00eb << 16) // RM, Logical +#define SL_ZOPC (unsigned int)(0x5f << 24) #define SLY_ZOPC (unsigned long)(227L << 40 | 95L) #define SLGF_ZOPC (unsigned long)(227L << 40 | 27L) #define SLG_ZOPC (unsigned long)(227L << 40 | 11L) @@ -1519,7 +1520,9 @@ class Assembler : public AbstractAssembler { //----------------------------------------------- // Calculate length of instruction. + static unsigned int instr_len(unsigned char len_bits); static unsigned int instr_len(unsigned char *instr); + static unsigned int instr_len(unsigned long instr); // Longest instructions are 6 bytes on z/Architecture. static unsigned int instr_maxlen() { return 6; } @@ -1597,6 +1600,8 @@ class Assembler : public AbstractAssembler { static int inv_simm32(long x) { return (inv_s_field(x, 31, 0)); } // 6-byte instructions only static int inv_uimm12(long x) { return (inv_u_field(x, 11, 0)); } // 4-byte instructions only + private: + // Encode u_field from long value. static long u_field(long x, int hi_bit, int lo_bit) { long r = x << lo_bit; @@ -1616,10 +1621,21 @@ class Assembler : public AbstractAssembler { else { guarantee(false, "bad address format"); return 0; } } - static int64_t rsmask_48( int64_t d2, Register b2) { return uimm12(d2, 20, 48) | regz(b2, 16, 48); } - static int64_t rxmask_48( int64_t d2, Register x2, Register b2) { return uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48); } - static int64_t rsymask_48(int64_t d2, Register b2) { return simm20(d2) | regz(b2, 16, 48); } - static int64_t rxymask_48(int64_t d2, Register x2, Register b2) { return simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48); } + static int64_t rsmask_32( int64_t d2, Register b2) { return uimm12(d2, 20, 32) | regz(b2, 16, 32); } + static int64_t rsmask_48( int64_t d2, Register b2) { return uimm12(d2, 20, 48) | regz(b2, 16, 48); } + static int64_t rsmask_SS( int64_t d2, Register b2) { return uimm12(d2, 36, 48) | regz(b2, 32, 48); } // storage-storage instructions + static int64_t rsymask_48(int64_t d2, Register b2) { return simm20(d2) | regz(b2, 16, 48); } + static int64_t rxmask_32( int64_t d2, Register x2, Register b2) { return uimm12(d2, 20, 32) | regt(x2, 12, 32) | regz(b2, 16, 32); } + static int64_t rxmask_48( int64_t d2, Register x2, Register b2) { return uimm12(d2, 20, 48) | regt(x2, 12, 48) | regz(b2, 16, 48); } + static int64_t rxymask_48(int64_t d2, Register x2, Register b2) { return simm20(d2) | regt(x2, 12, 48) | regz(b2, 16, 48); } + + // For instructions which use address calculation to derive an input value to the instruction. + // Shift instructions are an example of such use. + static int64_t rsmaskt_32( int64_t d2, Register b2) { return uimm12(d2, 20, 32) | regt(b2, 16, 32); } + static int64_t rsmaskt_48( int64_t d2, Register b2) { return uimm12(d2, 20, 48) | regt(b2, 16, 48); } + static int64_t rsymaskt_48(int64_t d2, Register b2) { return simm20(d2) | regt(b2, 16, 48); } + static int64_t rxmaskt_32( int64_t d2, Register x2, Register b2){ return uimm12(d2, 20, 32) | regt(x2, 12, 32) | regt(b2, 16, 32); } + static int64_t rxymaskt_48(int64_t d2, Register x2, Register b2){ return simm20(d2) | regt(x2, 12, 48) | regt(b2, 16, 48); } // Address calculated from d12(vx,b) - vx is vector index register. static int64_t rvmask_48( int64_t d2, VectorRegister x2, Register b2) { return uimm12(d2, 20, 48) | vreg(x2, 12) | regz(b2, 16, 48); } @@ -1717,8 +1733,8 @@ class Assembler : public AbstractAssembler { (((ui20 >> 12) & 0xffL) << (48-40))); // DH } - static long reg(Register r, int s, int len) { return u_field(r->encoding(), (len-s)-1, (len-s)-4); } - static long reg(int r, int s, int len) { return u_field(r, (len-s)-1, (len-s)-4); } + static long reg(int r, int s, int len) { return u_field(r, (len-s)-1, (len-s)-4); } + static long reg( Register r, int s, int len) { return reg(r->encoding(), s, len); } static long regt(Register r, int s, int len) { return reg(r, s, len); } static long regz(Register r, int s, int len) { assert(r != Z_R0, "cannot use register R0 in memory access"); return reg(r, s, len); } @@ -1792,9 +1808,11 @@ class Assembler : public AbstractAssembler { static unsigned int align(unsigned int x, unsigned int a) { return ((x + (a - 1)) & ~(a - 1)); } static bool is_aligned(unsigned int x, unsigned int a) { return (0 == x % a); } + inline unsigned int emit_instruction(unsigned long x, unsigned int len); inline void emit_16(int x); inline void emit_32(int x); inline void emit_48(long x); + inline void emit_data(int x); // Compare and control flow instructions // ===================================== @@ -2159,13 +2177,17 @@ class Assembler : public AbstractAssembler { // sub memory inline void z_s( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_imm12+x2+b2) ; int32 - inline void z_sy( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 + *(d2_imm20+s2+b2) ; int32 + inline void z_sy( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_imm20+s2+b2) ; int32 + inline void z_sl( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_uimm12+x2+b2); int32 + inline void z_sly( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_imm20+x2+b2) ; int32 inline void z_sg( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_imm12+x2+b2) ; int64 inline void z_sgf( Register r1, int64_t d2, Register x2, Register b2); // sub r1 = r1 - *(d2_imm12+x2+b2) ; int64 - int32 inline void z_slg( Register r1, int64_t d2, Register x2, Register b2); // sub logical r1 = r1 - *(d2_imm20+x2+b2) ; uint64 inline void z_slgf(Register r1, int64_t d2, Register x2, Register b2); // sub logical r1 = r1 - *(d2_imm20+x2+b2) ; uint64 - uint32 inline void z_s( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int32 inline void z_sy( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int32 + inline void z_sl( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int32 + inline void z_sly( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int32 inline void z_sg( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int64 inline void z_sgf( Register r1, const Address& a); // sub r1 = r1 - *(a) ; int64 - int32 inline void z_slg( Register r1, const Address& a); // sub r1 = r1 - *(a) ; uint64 diff --git a/src/hotspot/cpu/s390/assembler_s390.inline.hpp b/src/hotspot/cpu/s390/assembler_s390.inline.hpp index 31b674a55337246fda0316603bcb575f8a0af58e..d45869e4707b8eac79081cd60e125a147618492b 100644 --- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2021 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,30 +30,59 @@ #include "asm/codeBuffer.hpp" #include "code/codeCache.hpp" -// Convention: Use Z_R0 and Z_R1 instead of Z_scratch_* in all -// assembler_s390.* files. -// Local implementation of byte emitters to help inlining. +inline unsigned int Assembler::emit_instruction(unsigned long x, unsigned int len) { + CodeSection* cs = code_section(); + address pos = pc(); + assert(((intptr_t)pos & 0x01L) == 0, "instruction address alignment error"); + if (len == 0) { + len = instr_len(x); + } + + switch (len) { + case 2: + *(unsigned short*)(pos) = (unsigned short)x; + break; + case 4: + // May be unaligned store. Only slightly less efficient. + *(unsigned int*)(pos) = (unsigned int)x; + break; + case 6: + // Have to split anyway, so we can arrange for aligned stores. + if (((intptr_t)pos & 0x03) == 0) { + *(unsigned int*)pos = (unsigned int)(x>>16); + *(unsigned short*)(pos+4) = (unsigned short)x; + } else { + *(unsigned short*)(pos) = (unsigned short)(x>>32); + *(unsigned int*)(pos+2) = (unsigned int)x; + } + break; + default: + ShouldNotReachHere(); + break; + } + + assert(instr_len(pos) == len, "%d-byte emitter can't handle %d-byte instructions.", len, instr_len(pos)); + cs->set_end(pos + len); + return len; +} inline void Assembler::emit_16(int x) { - CodeSection* cs = code_section(); - address code_pos = pc(); - *(unsigned short*)code_pos = (unsigned short)x; - cs->set_end( code_pos + sizeof(unsigned short)); + emit_instruction((unsigned int)x, 2); } inline void Assembler::emit_32(int x) { - CodeSection* cs = code_section(); - address code_pos = pc(); - *(jint*)code_pos = (jint)x; - cs->set_end( code_pos + sizeof( jint)); + emit_instruction((unsigned int)x, 4); } inline void Assembler::emit_48(long x) { + emit_instruction((unsigned long)x, 6); +} + +inline void Assembler::emit_data(int x) { CodeSection* cs = code_section(); address code_pos = pc(); - *(unsigned short*)code_pos = (unsigned short)(x>>32); - *(jint*)(code_pos+sizeof(unsigned short)) = (jint)x; - cs->set_end( code_pos + sizeof( jint) + sizeof( unsigned short)); + *(int*)code_pos = x; + cs->set_end(code_pos + sizeof(int)); } // Support lightweight sync (from z196). Experimental as of now. For explanation see *.hpp file. @@ -104,26 +133,27 @@ inline void Assembler::z_kimd( Register r1, Register r2) { emit_32( KIMD_ZOPC inline void Assembler::z_klmd( Register r1, Register r2) { emit_32( KLMD_ZOPC | regt(r1, 24, 32) | regt(r2, 28, 32)); } inline void Assembler::z_kmac( Register r1, Register r2) { emit_32( KMAC_ZOPC | regt(r1, 24, 32) | regt(r2, 28, 32)); } -inline void Assembler::z_exrl(Register r1, int64_t i2) { emit_48( EXRL_ZOPC | regt(r1, 8, 48) | simm32(i2, 16, 48)); } // z10 -inline void Assembler::z_exrl(Register r1, address a2) { emit_48( EXRL_ZOPC | regt(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a2, pc()), 16, 48)); } // z10 +inline void Assembler::z_ex( Register r1, int64_t d2, Register x2, Register b2) { emit_32( EX_ZOPC | regz(r1, 8, 32) | rxmask_32(d2, x2, b2)); } +inline void Assembler::z_exrl(Register r1, int64_t i2) { emit_48( EXRL_ZOPC | regz(r1, 8, 48) | simm32(i2, 16, 48)); } // z10 +inline void Assembler::z_exrl(Register r1, address a2) { emit_48( EXRL_ZOPC | regz(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a2, pc()), 16, 48)); } // z10 -inline void Assembler::z_ectg(int64_t d1, Register b1, int64_t d2, Register b2, Register r3) { emit_48( ECTG_ZOPC | reg(r3, 8, 48) | uimm12(d1, 20, 48) | reg(b1, 16, 48) | uimm12(d2, 36, 48) | reg(b2, 32, 48)); } -inline void Assembler::z_ecag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( ECAG_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | reg(b2, 16, 48)); } +inline void Assembler::z_ectg( int64_t d1, Register b1, int64_t d2, Register b2, Register r3) { emit_48( ECTG_ZOPC | reg(r3, 8, 48) | rsmask_48(d1, b1) | rsmask_SS( d2, b2)); } +inline void Assembler::z_ecag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( ECAG_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | rsymaskt_48(d2, b2)); } //------------------------------ // Interlocked-Update //------------------------------ -inline void Assembler::z_laa( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAA_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_laag( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAAG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_laal( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAAL_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_laalg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAALG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_lan( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAN_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_lang( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LANG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_lax( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAX_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_laxg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAXG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_lao( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAO_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_laog( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAOG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } +inline void Assembler::z_laa( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAA_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_laag( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAAG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_laal( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAAL_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_laalg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAALG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_lan( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAN_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_lang( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LANG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_lax( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAX_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_laxg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAXG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_lao( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAO_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_laog( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LAOG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } inline void Assembler::z_laa( Register r1, Register r3, const Address& a) { assert(!a.has_index(), " no index reg allowed"); z_laa( r1, r3, a.disp12(), a.base()); } inline void Assembler::z_laag( Register r1, Register r3, const Address& a) { assert(!a.has_index(), " no index reg allowed"); z_laag( r1, r3, a.disp12(), a.base()); } @@ -139,33 +169,33 @@ inline void Assembler::z_laog( Register r1, Register r3, const Address& a) { ass //-------------------------------- // Execution Prediction //-------------------------------- -inline void Assembler::z_pfd( int64_t m1, int64_t d2, Register x2, Register b2) { emit_48( PFD_ZOPC | uimm4(m1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_pfd( int64_t m1, int64_t d2, Register x2, Register b2) { emit_48( PFD_ZOPC | uimm4(m1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_pfd( int64_t m1, Address a) { z_pfd(m1, a.disp(), a.indexOrR0(), a.base()); } inline void Assembler::z_pfdrl(int64_t m1, int64_t i2) { emit_48( PFDRL_ZOPC | uimm4(m1, 8, 48) | simm32(i2, 16, 48)); } -inline void Assembler::z_bpp( int64_t m1, int64_t i2, int64_t d3, Register b3) { emit_48( BPP_ZOPC | uimm4(m1, 8, 48) | uimm12(d3, 20, 48) | reg(b3, 16, 48) | simm16(i2, 32, 48)); } +inline void Assembler::z_bpp( int64_t m1, int64_t i2, int64_t d3, Register b3) { emit_48( BPP_ZOPC | uimm4(m1, 8, 48) | rsmask_48(d3, b3) | simm16(i2, 32, 48)); } inline void Assembler::z_bprp( int64_t m1, int64_t i2, int64_t i3) { emit_48( BPRP_ZOPC | uimm4(m1, 8, 48) | simm12(i2, 12, 48) | simm24(i3, 24, 48)); } //------------------------------- // Transaction Control //------------------------------- -inline void Assembler::z_tbegin( int64_t d1, Register b1, int64_t i2) { emit_48( TBEGIN_ZOPC | uimm12(d1, 20, 48) | reg(b1, 16, 48) | uimm16(i2, 32, 48)); } -inline void Assembler::z_tbeginc(int64_t d1, Register b1, int64_t i2) { emit_48( TBEGINC_ZOPC | uimm12(d1, 20, 48) | reg(b1, 16, 48) | uimm16(i2, 32, 48)); } +inline void Assembler::z_tbegin( int64_t d1, Register b1, int64_t i2) { emit_48( TBEGIN_ZOPC | rsmask_48(d1, b1) | uimm16(i2, 32, 48)); } +inline void Assembler::z_tbeginc(int64_t d1, Register b1, int64_t i2) { emit_48( TBEGINC_ZOPC | rsmask_48(d1, b1) | uimm16(i2, 32, 48)); } inline void Assembler::z_tend() { emit_32( TEND_ZOPC); } -inline void Assembler::z_tabort( int64_t d2, Register b2) { emit_32( TABORT_ZOPC | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_tabort( int64_t d2, Register b2) { emit_32( TABORT_ZOPC | rsmask_32(d2, b2)); } inline void Assembler::z_etnd(Register r1) { emit_32( ETND_ZOPC | regt(r1, 24, 32)); } inline void Assembler::z_ppa(Register r1, Register r2, int64_t m3) { emit_32( PPA_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } //--------------------------------- // Conditional Execution //--------------------------------- -inline void Assembler::z_locr( Register r1, Register r2, branch_condition cc) { emit_32( LOCR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | uimm4(cc, 16, 32)); } // z196 -inline void Assembler::z_locgr( Register r1, Register r2, branch_condition cc) { emit_32( LOCGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | uimm4(cc, 16, 32)); } // z196 -inline void Assembler::z_loc( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( LOC_ZOPC | regt(r1, 8, 48) | simm20(d2) | regz(b2, 16, 48) | uimm4(cc, 12, 48)); } // z196 -inline void Assembler::z_locg( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( LOCG_ZOPC | regt(r1, 8, 48) | simm20(d2) | regz(b2, 16, 48) | uimm4(cc, 12, 48)); } // z196 -inline void Assembler::z_loc( Register r1, const Address &a, branch_condition cc) { z_loc(r1, a.disp(), a.base(), cc); } +inline void Assembler::z_locr( Register r1, Register r2, branch_condition cc) { emit_32( LOCR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | uimm4(cc, 16, 32)); } // z196 +inline void Assembler::z_locgr( Register r1, Register r2, branch_condition cc) { emit_32( LOCGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | uimm4(cc, 16, 32)); } // z196 +inline void Assembler::z_loc( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( LOC_ZOPC | regt(r1, 8, 48) | rsymask_48(d2, b2) | uimm4(cc, 12, 48)); } // z196 +inline void Assembler::z_locg( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( LOCG_ZOPC | regt(r1, 8, 48) | rsymask_48(d2, b2) | uimm4(cc, 12, 48)); } // z196 +inline void Assembler::z_loc( Register r1, const Address &a, branch_condition cc) { z_loc(r1, a.disp(), a.base(), cc); } inline void Assembler::z_locg( Register r1, const Address &a, branch_condition cc) { z_locg(r1, a.disp(), a.base(), cc); } -inline void Assembler::z_stoc( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( STOC_ZOPC | regt(r1, 8, 48) | simm20(d2) | regz(b2, 16, 48) | uimm4(cc, 12, 48)); } // z196 -inline void Assembler::z_stocg( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( STOCG_ZOPC | regt(r1, 8, 48) | simm20(d2) | regz(b2, 16, 48) | uimm4(cc, 12, 48)); } // z196 +inline void Assembler::z_stoc( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( STOC_ZOPC | regt(r1, 8, 48) | rsymask_48(d2, b2) | uimm4(cc, 12, 48)); } // z196 +inline void Assembler::z_stocg( Register r1, int64_t d2, Register b2, branch_condition cc) { emit_48( STOCG_ZOPC | regt(r1, 8, 48) | rsymask_48(d2, b2) | uimm4(cc, 12, 48)); } // z196 inline void Assembler::z_srst( Register r1, Register r2) { emit_32( SRST_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_srstu(Register r1, Register r2) { emit_32( SRSTU_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } @@ -173,26 +203,29 @@ inline void Assembler::z_srstu(Register r1, Register r2) { emit_32( SRSTU_ZOPC | //--------------------------------- // Address calculation //--------------------------------- -inline void Assembler::z_layz(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LAY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | reg(b2, 16, 48)); } +inline void Assembler::z_layz(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LAY_ZOPC | regt(r1, 8, 48) | rxymaskt_48(d2, x2, b2)); } +inline void Assembler::z_lay( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LAY_ZOPC | regt(r1, 8, 48) | rxymask_48( d2, x2, b2)); } +inline void Assembler::z_laz( Register r1, int64_t d2, Register x2, Register b2) { emit_32( LA_ZOPC | regt(r1, 8, 32) | rxmaskt_32( d2, x2, b2)); } +inline void Assembler::z_la( Register r1, int64_t d2, Register x2, Register b2) { emit_32( LA_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } inline void Assembler::z_lay( Register r1, const Address &a) { z_layz(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lay( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LAY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_laz( Register r1, int64_t d2, Register x2, Register b2) { emit_32( LA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_la( Register r1, const Address &a) { z_laz(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_la( Register r1, int64_t d2, Register x2, Register b2) { emit_32( LA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32));} +inline void Assembler::z_la( Register r1, const Address &a) { z_laz( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_larl(Register r1, int64_t i2) { emit_48( LARL_ZOPC | regt(r1, 8, 48) | simm32(i2, 16, 48)); } inline void Assembler::z_larl(Register r1, address a) { emit_48( LARL_ZOPC | regt(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } -inline void Assembler::z_lr(Register r1, Register r2) { emit_16( LR_ZOPC | regt(r1,8,16) | reg(r2,12,16)); } -inline void Assembler::z_lgr(Register r1, Register r2) { emit_32( LGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_lh(Register r1, int64_t d2, Register x2, Register b2) { emit_32( LH_ZOPC | 0 << 16 | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_lh(Register r1, const Address &a) { z_lh(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_l(Register r1, int64_t d2, Register x2, Register b2) { emit_32( L_ZOPC | 0 << 16 | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_l(Register r1, const Address &a) { z_l(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lg(Register r1, const Address &a) { z_lg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } - -inline void Assembler::z_lbr( Register r1, Register r2) { emit_32( LBR_ZOPC | regt(r1, 24, 32) | reg( r2, 28, 32)); } -inline void Assembler::z_lhr( Register r1, Register r2) { emit_32( LHR_ZOPC | regt(r1, 24, 32) | reg( r2, 28, 32)); } +//--------------------------------- +// Load/Store +//--------------------------------- +inline void Assembler::z_lr( Register r1, Register r2) { emit_16( LR_ZOPC | regt(r1, 8, 16) | reg(r2, 12, 16)); } +inline void Assembler::z_lgr(Register r1, Register r2) { emit_32( LGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_lh( Register r1, int64_t d2, Register x2, Register b2) { emit_32( LH_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_l( Register r1, int64_t d2, Register x2, Register b2) { emit_32( L_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_lg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lh( Register r1, const Address &a) { z_lh(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_l( Register r1, const Address &a) { z_l( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_lg( Register r1, const Address &a) { z_lg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } + +inline void Assembler::z_lbr( Register r1, Register r2) { emit_32( LBR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_lhr( Register r1, Register r2) { emit_32( LHR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_lgbr( Register r1, Register r2) { emit_32( LGBR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_lghr( Register r1, Register r2) { emit_32( LGHR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_lgfr( Register r1, Register r2) { emit_32( LGFR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } @@ -201,30 +234,30 @@ inline void Assembler::z_llgcr(Register r1, Register r2) { emit_32( LLGCR_ZOPC | inline void Assembler::z_llghr(Register r1, Register r2) { emit_32( LLGHR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_llgfr(Register r1, Register r2) { emit_32( LLGFR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_sth(Register r1, int64_t d2, Register x2, Register b2) { emit_32( STH_ZOPC | reg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_st( Register r1, int64_t d2, Register x2, Register b2) { emit_32( ST_ZOPC | reg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_stg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( STG_ZOPC | reg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_sth(Register r1, const Address &a) { z_sth(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_sth(Register r1, int64_t d2, Register x2, Register b2) { emit_32( STH_ZOPC | reg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_st( Register r1, const Address& d) { z_st(r1, d.disp(), d.indexOrR0(), d.base()); } -inline void Assembler::z_st( Register r1, int64_t d2, Register x2, Register b2) { emit_32( ST_ZOPC | reg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stg(Register r1, const Address& d) { z_stg(r1, d.disp(), d.indexOrR0(), d.base()); } -inline void Assembler::z_stg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( STG_ZOPC | reg(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_st( Register r1, const Address &a) { z_st( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_stg(Register r1, const Address &a) { z_stg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_stcm (Register r1, int64_t m3, int64_t d2, Register b2) { emit_32( STCM_ZOPC | regt(r1, 8, 32) | uimm4(m3, 12, 32) | uimm12(d2, 20, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stcmy(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( STCMY_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_stcmh(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( STCMH_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } +inline void Assembler::z_stcm (Register r1, int64_t m3, int64_t d2, Register b2) { emit_32( STCM_ZOPC | regt(r1, 8, 32) | uimm4(m3, 12, 32) | rsmask_32( d2, b2)); } +inline void Assembler::z_stcmy(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( STCMY_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_stcmh(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( STCMH_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | rsymask_48(d2, b2)); } // memory-immediate instructions (8-bit immediate) -inline void Assembler::z_cli( int64_t d1, Register b1, int64_t i2) { emit_32( CLI_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | uimm8(i2, 8, 32)); } -inline void Assembler::z_mvi( int64_t d1, Register b1, int64_t i2) { emit_32( MVI_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | imm8(i2, 8, 32)); } -inline void Assembler::z_tm( int64_t d1, Register b1, int64_t i2) { emit_32( TM_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | imm8(i2, 8, 32)); } -inline void Assembler::z_ni( int64_t d1, Register b1, int64_t i2) { emit_32( NI_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | imm8(i2, 8, 32)); } -inline void Assembler::z_oi( int64_t d1, Register b1, int64_t i2) { emit_32( OI_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | imm8(i2, 8, 32)); } -inline void Assembler::z_xi( int64_t d1, Register b1, int64_t i2) { emit_32( XI_ZOPC | uimm12(d1, 20, 32) | regz(b1, 16, 32) | imm8(i2, 8, 32)); } -inline void Assembler::z_cliy(int64_t d1, Register b1, int64_t i2) { emit_48( CLIY_ZOPC | simm20(d1) | regz(b1, 16, 48) | uimm8(i2, 8, 48)); } -inline void Assembler::z_mviy(int64_t d1, Register b1, int64_t i2) { emit_48( MVIY_ZOPC | simm20(d1) | regz(b1, 16, 48) | imm8(i2, 8, 48)); } -inline void Assembler::z_tmy( int64_t d1, Register b1, int64_t i2) { emit_48( TMY_ZOPC | simm20(d1) | regz(b1, 16, 48) | imm8(i2, 8, 48)); } -inline void Assembler::z_niy( int64_t d1, Register b1, int64_t i2) { emit_48( NIY_ZOPC | simm20(d1) | regz(b1, 16, 48) | imm8(i2, 8, 48)); } -inline void Assembler::z_oiy( int64_t d1, Register b1, int64_t i2) { emit_48( OIY_ZOPC | simm20(d1) | regz(b1, 16, 48) | imm8(i2, 8, 48)); } -inline void Assembler::z_xiy( int64_t d1, Register b1, int64_t i2) { emit_48( XIY_ZOPC | simm20(d1) | regz(b1, 16, 48) | imm8(i2, 8, 48)); } +inline void Assembler::z_cli( int64_t d1, Register b1, int64_t i2) { emit_32( CLI_ZOPC | rsmask_32( d1, b1) | uimm8(i2, 8, 32)); } +inline void Assembler::z_mvi( int64_t d1, Register b1, int64_t i2) { emit_32( MVI_ZOPC | rsmask_32( d1, b1) | imm8(i2, 8, 32)); } +inline void Assembler::z_tm( int64_t d1, Register b1, int64_t i2) { emit_32( TM_ZOPC | rsmask_32( d1, b1) | imm8(i2, 8, 32)); } +inline void Assembler::z_ni( int64_t d1, Register b1, int64_t i2) { emit_32( NI_ZOPC | rsmask_32( d1, b1) | imm8(i2, 8, 32)); } +inline void Assembler::z_oi( int64_t d1, Register b1, int64_t i2) { emit_32( OI_ZOPC | rsmask_32( d1, b1) | imm8(i2, 8, 32)); } +inline void Assembler::z_xi( int64_t d1, Register b1, int64_t i2) { emit_32( XI_ZOPC | rsmask_32( d1, b1) | imm8(i2, 8, 32)); } +inline void Assembler::z_cliy(int64_t d1, Register b1, int64_t i2) { emit_48( CLIY_ZOPC | rsymask_48(d1, b1) | uimm8(i2, 8, 48)); } +inline void Assembler::z_mviy(int64_t d1, Register b1, int64_t i2) { emit_48( MVIY_ZOPC | rsymask_48(d1, b1) | imm8(i2, 8, 48)); } +inline void Assembler::z_tmy( int64_t d1, Register b1, int64_t i2) { emit_48( TMY_ZOPC | rsymask_48(d1, b1) | imm8(i2, 8, 48)); } +inline void Assembler::z_niy( int64_t d1, Register b1, int64_t i2) { emit_48( NIY_ZOPC | rsymask_48(d1, b1) | imm8(i2, 8, 48)); } +inline void Assembler::z_oiy( int64_t d1, Register b1, int64_t i2) { emit_48( OIY_ZOPC | rsymask_48(d1, b1) | imm8(i2, 8, 48)); } +inline void Assembler::z_xiy( int64_t d1, Register b1, int64_t i2) { emit_48( XIY_ZOPC | rsymask_48(d1, b1) | imm8(i2, 8, 48)); } inline void Assembler::z_cli( const Address& a, int64_t imm) { assert(!a.has_index(), " no index reg allowed in CLI"); z_cli( a.disp12(), a.base(), imm); } inline void Assembler::z_mvi( const Address& a, int64_t imm) { assert(!a.has_index(), " no index reg allowed in CLI"); z_mvi( a.disp12(), a.base(), imm); } @@ -244,61 +277,58 @@ inline void Assembler::z_mvc(const Address& d, const Address& s, int64_t l) { assert(!d.has_index() && !s.has_index(), "Address operand can not be encoded."); z_mvc(d.disp(), l-1, d.base(), s.disp(), s.base()); } -inline void Assembler::z_mvc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( MVC_ZOPC | uimm12(d1, 20, 48) | uimm8(l, 8, 48) | regz(b1, 16, 48) | uimm12(d2, 36, 48) | regz(b2, 32, 48)); } -inline void Assembler::z_mvcle(Register r1, Register r3, int64_t d2, Register b2) { emit_32( MVCLE_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_mvc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( MVC_ZOPC | uimm8(l, 8, 48) | rsmask_48(d1, b1) | rsmask_SS(d2, b2)); } +inline void Assembler::z_mvcle(Register r1, Register r3, int64_t d2, Register b2) { emit_32( MVCLE_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | rsmaskt_32(d2, b2)); } -inline void Assembler::z_mvhhi( int64_t d1, Register b1, int64_t i2) { emit_48( MVHHI_ZOPC | uimm12( d1, 20, 48) | regz(b1, 16, 48) | simm16(i2, 32, 48)); } -inline void Assembler::z_mvhi ( int64_t d1, Register b1, int64_t i2) { emit_48( MVHI_ZOPC | uimm12( d1, 20, 48) | regz(b1, 16, 48) | simm16(i2, 32, 48)); } -inline void Assembler::z_mvghi( int64_t d1, Register b1, int64_t i2) { emit_48( MVGHI_ZOPC | uimm12( d1, 20, 48) | regz(b1, 16, 48) | simm16(i2, 32, 48)); } +inline void Assembler::z_mvhhi( int64_t d1, Register b1, int64_t i2) { emit_48( MVHHI_ZOPC | rsmask_48( d1, b1) | simm16(i2, 32, 48)); } +inline void Assembler::z_mvhi ( int64_t d1, Register b1, int64_t i2) { emit_48( MVHI_ZOPC | rsmask_48( d1, b1) | simm16(i2, 32, 48)); } +inline void Assembler::z_mvghi( int64_t d1, Register b1, int64_t i2) { emit_48( MVGHI_ZOPC | rsmask_48( d1, b1) | simm16(i2, 32, 48)); } inline void Assembler::z_mvhhi( const Address &d, int64_t i2) { assert(!d.has_index(), " no index reg allowed in MVHHI"); z_mvhhi( d.disp(), d.baseOrR0(), i2); } inline void Assembler::z_mvhi ( const Address &d, int64_t i2) { assert(!d.has_index(), " no index reg allowed in MVHI"); z_mvhi( d.disp(), d.baseOrR0(), i2); } inline void Assembler::z_mvghi( const Address &d, int64_t i2) { assert(!d.has_index(), " no index reg allowed in MVGHI"); z_mvghi( d.disp(), d.baseOrR0(), i2); } -inline void Assembler::z_ex(Register r1, int64_t d2, Register x2, Register b2) { emit_32( EX_ZOPC | regz(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } - -inline void Assembler::z_ic (Register r1, int64_t d2, Register x2, Register b2) { emit_32( IC_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_icy (Register r1, int64_t d2, Register x2, Register b2) { emit_48( ICY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_icm (Register r1, int64_t m3, int64_t d2, Register b2) { emit_32( ICM_ZOPC | regt(r1, 8, 32) | uimm4(m3, 12, 32) | uimm12(d2, 20, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_icmy(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( ICMY_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } -inline void Assembler::z_icmh(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( ICMH_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | simm20(d2) | regz(b2, 16, 48)); } +inline void Assembler::z_ic (Register r1, int64_t d2, Register x2, Register b2) { emit_32( IC_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_icy (Register r1, int64_t d2, Register x2, Register b2) { emit_48( ICY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_icm (Register r1, int64_t m3, int64_t d2, Register b2) { emit_32( ICM_ZOPC | regt(r1, 8, 32) | uimm4(m3, 12, 32) | rsmask_32( d2, b2)); } +inline void Assembler::z_icmy(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( ICMY_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_icmh(Register r1, int64_t m3, int64_t d2, Register b2) { emit_48( ICMH_ZOPC | regt(r1, 8, 48) | uimm4(m3, 12, 48) | rsymask_48(d2, b2)); } inline void Assembler::z_iihh(Register r1, int64_t i2) { emit_32( IIHH_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } inline void Assembler::z_iihl(Register r1, int64_t i2) { emit_32( IIHL_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } inline void Assembler::z_iilh(Register r1, int64_t i2) { emit_32( IILH_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } inline void Assembler::z_iill(Register r1, int64_t i2) { emit_32( IILL_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } inline void Assembler::z_iihf(Register r1, int64_t i2) { emit_48( IIHF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_iilf(Register r1, int64_t i2) { emit_48( IILF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } -inline void Assembler::z_lgf(Register r1, const Address& a) { z_lgf(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lhy(Register r1, const Address &a) { z_lhy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lhy(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LHY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lgh(Register r1, const Address &a) { z_lgh(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lgh(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGH_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lt(Register r1, const Address &a) { z_lt(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lt (Register r1, int64_t d2, Register x2, Register b2) { emit_48( LT_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ltg(Register r1, const Address &a) { z_ltg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ltg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LTG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_lgf( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lhy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LHY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lgh( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGH_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lt ( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LT_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ltg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LTG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ltgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LTGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lb ( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LB_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lgb( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGB_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ly( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_llc( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLC_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_llh( Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLH_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_llgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_llgh(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGH_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_llgc(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGC_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_lgf( Register r1, const Address &a) { z_lgf( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_lhy( Register r1, const Address &a) { z_lhy( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_lgh( Register r1, const Address &a) { z_lgh( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_lt( Register r1, const Address &a) { z_lt( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ltg( Register r1, const Address &a) { z_ltg( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_ltgf(Register r1, const Address &a) { z_ltgf(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ltgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LTGF_ZOPC| regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lb(Register r1, const Address &a) { z_lb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lb (Register r1, int64_t d2, Register x2, Register b2) { emit_48( LB_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_lgb(Register r1, const Address &a) { z_lgb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lgb(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LGB_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ly(Register r1, const Address &a) { z_ly(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ly(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_llc(Register r1, const Address& a) { z_llc(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_llc(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLC_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_llh(Register r1, const Address &a) { z_llh(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_llh(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLH_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_lb( Register r1, const Address &a) { z_lb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_lgb( Register r1, const Address &a) { z_lgb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ly( Register r1, const Address &a) { z_ly( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_llc( Register r1, const Address &a) { z_llc( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_llh( Register r1, const Address &a) { z_llh( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_llgf(Register r1, const Address &a) { z_llgf(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_llgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } inline void Assembler::z_llgh(Register r1, const Address &a) { z_llgh(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_llgh(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGH_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } inline void Assembler::z_llgc(Register r1, const Address &a) { z_llgc(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_llgc(Register r1, int64_t d2, Register x2, Register b2) { emit_48( LLGC_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_llgc(Register r1, int64_t d2, Register b2) { z_llgc( r1, d2, Z_R0, b2); } -inline void Assembler::z_lhi(Register r1, int64_t i2) { emit_32( LHI_ZOPC | regt(r1, 8, 32) | simm16(i2, 16, 32)); } -inline void Assembler::z_lghi(Register r1, int64_t i2) { emit_32( LGHI_ZOPC | regt(r1, 8, 32) | simm16(i2, 16, 32)); } -inline void Assembler::z_lgfi(Register r1, int64_t i2) { emit_48( LGFI_ZOPC | regt(r1, 8, 48) | simm32(i2, 16, 48)); } +inline void Assembler::z_lhi( Register r1, int64_t i2) { emit_32( LHI_ZOPC | regt(r1, 8, 32) | simm16(i2, 16, 32)); } +inline void Assembler::z_lghi( Register r1, int64_t i2) { emit_32( LGHI_ZOPC | regt(r1, 8, 32) | simm16(i2, 16, 32)); } +inline void Assembler::z_lgfi( Register r1, int64_t i2) { emit_48( LGFI_ZOPC | regt(r1, 8, 48) | simm32(i2, 16, 48)); } inline void Assembler::z_llihf(Register r1, int64_t i2) { emit_48( LLIHF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_llilf(Register r1, int64_t i2) { emit_48( LLILF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_llihh(Register r1, int64_t i2) { emit_32( LLIHH_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } @@ -323,36 +353,37 @@ inline void Assembler::z_lrvgr(Register r1, Register r2) { emit_32( LRVGR_ZOPC | inline void Assembler::z_ltr( Register r1, Register r2) { emit_16( LTR_ZOPC | regt(r1, 8, 16) | reg(r2, 12, 16)); } inline void Assembler::z_ltgr( Register r1, Register r2) { emit_32( LTGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_ltgfr(Register r1, Register r2) { emit_32( LTGFR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_stc( Register r1, const Address &a) { z_stc(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_stc( Register r1, int64_t d2, Register x2, Register b2) { emit_32( STC_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } +inline void Assembler::z_stc( Register r1, int64_t d2, Register x2, Register b2) { emit_32( STC_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_stcy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STCY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_sthy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STHY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_sty( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_stc( Register r1, const Address &a) { z_stc( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_stcy( Register r1, const Address &a) { z_stcy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_stcy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STCY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } inline void Assembler::z_sthy( Register r1, const Address &a) { z_sthy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_sthy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STHY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_sty( Register r1, const Address &a) { z_sty(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_sty( Register r1, int64_t d2, Register x2, Register b2) { emit_48( STY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_stfle(int64_t d2, Register b2) { emit_32(STFLE_ZOPC | uimm12(d2,20,32) | regz(b2,16,32)); } +inline void Assembler::z_sty( Register r1, const Address &a) { z_sty( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } + +inline void Assembler::z_stfle(int64_t d2, Register b2) { emit_32(STFLE_ZOPC | rsmask_32(d2, b2)); } //----------------------------------- // SHIFT/RORATE OPERATIONS //----------------------------------- -inline void Assembler::z_sla( Register r1, int64_t d2, Register b2) { emit_32( SLA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_slak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_slag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_sra( Register r1, int64_t d2, Register b2) { emit_32( SRA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_srak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_srag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_sll( Register r1, int64_t d2, Register b2) { emit_32( SLL_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_sllk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_sllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_srl( Register r1, int64_t d2, Register b2) { emit_32( SRL_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_srlk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } -inline void Assembler::z_srlg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } +inline void Assembler::z_sla( Register r1, int64_t d2, Register b2) { emit_32( SLA_ZOPC | regt(r1, 8, 32) | rsmaskt_32( d2, b2)); } +inline void Assembler::z_slak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAK_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_slag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAG_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_sra( Register r1, int64_t d2, Register b2) { emit_32( SRA_ZOPC | regt(r1, 8, 32) | rsmaskt_32( d2, b2)); } +inline void Assembler::z_srak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAK_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_srag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAG_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_sll( Register r1, int64_t d2, Register b2) { emit_32( SLL_ZOPC | regt(r1, 8, 32) | rsmaskt_32( d2, b2)); } +inline void Assembler::z_sllk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLK_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_sllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLG_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_srl( Register r1, int64_t d2, Register b2) { emit_32( SRL_ZOPC | regt(r1, 8, 32) | rsmaskt_32( d2, b2)); } +inline void Assembler::z_srlk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLK_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_srlg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLG_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } // rotate left -inline void Assembler::z_rll( Register r1, Register r3, int64_t d2, Register b2) { emit_48( RLL_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | reg(b2, 16, 48)); } -inline void Assembler::z_rllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( RLLG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm20(d2) | reg(b2, 16, 48)); } +inline void Assembler::z_rll( Register r1, Register r3, int64_t d2, Register b2) { emit_48( RLL_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } +inline void Assembler::z_rllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( RLLG_ZOPC | regt(r1, 8, 48) | rsymaskt_48(d2, b2) | reg(r3, 12, 48)); } // Rotate the AND/XOR/OR/insert inline void Assembler::z_rnsbg( Register r1, Register r2, int64_t spos3, int64_t epos4, int64_t nrot5, bool test_only) { // Rotate then AND selected bits. -- z196 @@ -388,9 +419,9 @@ inline void Assembler::z_risbg( Register r1, Register r2, int64_t spos3, int64_t //------------------------------ // LOGICAL OPERATIONS //------------------------------ -inline void Assembler::z_n( Register r1, int64_t d2, Register x2, Register b2) { emit_32( N_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_ny( Register r1, int64_t d2, Register x2, Register b2) { emit_48( NY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ng( Register r1, int64_t d2, Register x2, Register b2) { emit_48( NG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_n( Register r1, int64_t d2, Register x2, Register b2) { emit_32( N_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_ny( Register r1, int64_t d2, Register x2, Register b2) { emit_48( NY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ng( Register r1, int64_t d2, Register x2, Register b2) { emit_48( NG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_n( Register r1, const Address& a) { z_n( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_ny( Register r1, const Address& a) { z_ny(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_ng( Register r1, const Address& a) { z_ng(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -407,9 +438,9 @@ inline void Assembler::z_nill(Register r1, int64_t i2) { emit_32( NILL_ZOPC | re inline void Assembler::z_nihf(Register r1, int64_t i2) { emit_48( NIHF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_nilf(Register r1, int64_t i2) { emit_48( NILF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } -inline void Assembler::z_o( Register r1, int64_t d2, Register x2, Register b2) { emit_32( O_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_oy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( OY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_og( Register r1, int64_t d2, Register x2, Register b2) { emit_48( OG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_o( Register r1, int64_t d2, Register x2, Register b2) { emit_32( O_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_oy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( OY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_og( Register r1, int64_t d2, Register x2, Register b2) { emit_48( OG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_o( Register r1, const Address& a) { z_o( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_oy( Register r1, const Address& a) { z_oy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_og( Register r1, const Address& a) { z_og(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -426,9 +457,9 @@ inline void Assembler::z_oill(Register r1, int64_t i2) { emit_32( OILL_ZOPC | re inline void Assembler::z_oihf(Register r1, int64_t i2) { emit_48( OIHF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_oilf(Register r1, int64_t i2) { emit_48( OILF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } -inline void Assembler::z_x( Register r1, int64_t d2, Register x2, Register b2) { emit_32( X_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_xy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( XY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_xg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( XG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_x( Register r1, int64_t d2, Register x2, Register b2) { emit_32( X_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_xy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( XY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_xg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( XG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_x( Register r1, const Address& a) { z_x( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_xy( Register r1, const Address& a) { z_xy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_xg( Register r1, const Address& a) { z_xg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -441,9 +472,9 @@ inline void Assembler::z_xgrk(Register r1, Register r2, Register r3) { emit_32( inline void Assembler::z_xihf(Register r1, int64_t i2) { emit_48( XIHF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } inline void Assembler::z_xilf(Register r1, int64_t i2) { emit_48( XILF_ZOPC | regt(r1, 8, 48) | imm32(i2, 16, 48)); } -inline void Assembler::z_nc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( NC_ZOPC | uimm12(d1, 20, 48) | uimm8(l, 8, 48) | regz(b1, 16, 48) | uimm12(d2, 36, 48) | regz(b2, 32, 48)); } -inline void Assembler::z_oc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( OC_ZOPC | uimm12(d1, 20, 48) | uimm8(l, 8, 48) | regz(b1, 16, 48) | uimm12(d2, 36, 48) | regz(b2, 32, 48)); } -inline void Assembler::z_xc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( XC_ZOPC | uimm12(d1, 20, 48) | uimm8(l, 8, 48) | regz(b1, 16, 48) | uimm12(d2, 36, 48) | regz(b2, 32, 48)); } +inline void Assembler::z_nc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( NC_ZOPC | uimm8(l, 8, 48) | rsmask_48(d1, b1) | rsmask_SS(d2, b2)); } +inline void Assembler::z_oc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( OC_ZOPC | uimm8(l, 8, 48) | rsmask_48(d1, b1) | rsmask_SS(d2, b2)); } +inline void Assembler::z_xc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( XC_ZOPC | uimm8(l, 8, 48) | rsmask_48(d1, b1) | rsmask_SS(d2, b2)); } inline void Assembler::z_nc(Address dst, int64_t len, Address src2) { assert(!dst.has_index() && !src2.has_index(), "Cannot encode index"); z_nc(dst.disp12(), len-1, dst.base(), src2.disp12(), src2.base()); } inline void Assembler::z_oc(Address dst, int64_t len, Address src2) { assert(!dst.has_index() && !src2.has_index(), "Cannot encode index"); z_oc(dst.disp12(), len-1, dst.base(), src2.disp12(), src2.base()); } inline void Assembler::z_xc(Address dst, int64_t len, Address src2) { assert(!dst.has_index() && !src2.has_index(), "Cannot encode index"); z_xc(dst.disp12(), len-1, dst.base(), src2.disp12(), src2.base()); } @@ -452,14 +483,14 @@ inline void Assembler::z_xc(Address dst, int64_t len, Address src2) { assert(!ds //--------------- // ADD //--------------- -inline void Assembler::z_a( Register r1, int64_t d2, Register x2, Register b2) { emit_32( A_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_ay( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_al( Register r1, int64_t d2, Register x2, Register b2) { emit_32( AL_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_aly( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ag( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_agf( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_alg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_algf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_a( Register r1, int64_t d2, Register x2, Register b2) { emit_32( A_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_ay( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_al( Register r1, int64_t d2, Register x2, Register b2) { emit_32( AL_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_aly( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ag( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_agf( Register r1, int64_t d2, Register x2, Register b2) { emit_48( AGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_alg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_algf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( ALGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_a( Register r1, const Address& a) { z_a( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_ay( Register r1, const Address& a) { z_ay( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_al( Register r1, const Address& a) { z_al( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -501,10 +532,10 @@ inline void Assembler::z_alhsik( Register r1, Register r3, int64_t i2) { emit_48 inline void Assembler::z_alghsik(Register r1, Register r3, int64_t i2) { emit_48( ALGHSIK_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | simm16(i2, 16, 48)); } // In-memory arithmetic (add signed, add logical with signed immediate) -inline void Assembler::z_asi( int64_t d1, Register b1, int64_t i2) { emit_48( ASI_ZOPC | simm8(i2, 8, 48) | simm20(d1) | regz(b1, 16, 48)); } -inline void Assembler::z_agsi( int64_t d1, Register b1, int64_t i2) { emit_48( AGSI_ZOPC | simm8(i2, 8, 48) | simm20(d1) | regz(b1, 16, 48)); } -inline void Assembler::z_alsi( int64_t d1, Register b1, int64_t i2) { emit_48( ALSI_ZOPC | simm8(i2, 8, 48) | simm20(d1) | regz(b1, 16, 48)); } -inline void Assembler::z_algsi(int64_t d1, Register b1, int64_t i2) { emit_48( ALGSI_ZOPC | simm8(i2, 8, 48) | simm20(d1) | regz(b1, 16, 48)); } +inline void Assembler::z_asi( int64_t d1, Register b1, int64_t i2) { emit_48( ASI_ZOPC | simm8(i2, 8, 48) | rsymask_48(d1, b1)); } +inline void Assembler::z_agsi( int64_t d1, Register b1, int64_t i2) { emit_48( AGSI_ZOPC | simm8(i2, 8, 48) | rsymask_48(d1, b1)); } +inline void Assembler::z_alsi( int64_t d1, Register b1, int64_t i2) { emit_48( ALSI_ZOPC | simm8(i2, 8, 48) | rsymask_48(d1, b1)); } +inline void Assembler::z_algsi(int64_t d1, Register b1, int64_t i2) { emit_48( ALGSI_ZOPC | simm8(i2, 8, 48) | rsymask_48(d1, b1)); } inline void Assembler::z_asi( const Address& d, int64_t i2) { assert(!d.has_index(), "No index in ASI"); z_asi( d.disp(), d.base(), i2); } inline void Assembler::z_agsi( const Address& d, int64_t i2) { assert(!d.has_index(), "No index in AGSI"); z_agsi( d.disp(), d.base(), i2); } inline void Assembler::z_alsi( const Address& d, int64_t i2) { assert(!d.has_index(), "No index in ALSI"); z_alsi( d.disp(), d.base(), i2); } @@ -514,14 +545,18 @@ inline void Assembler::z_algsi(const Address& d, int64_t i2) { assert(!d.has_ind //-------------------- // SUBTRACT //-------------------- -inline void Assembler::z_s( Register r1, int64_t d2, Register x2, Register b2) { emit_32( S_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_sy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_sg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_sgf( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_slg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_slgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( SLGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_s( Register r1, int64_t d2, Register x2, Register b2) { emit_32( S_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_sy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_sl( Register r1, int64_t d2, Register x2, Register b2) { emit_32( SL_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_sly( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SLY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_sg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_sgf( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_slg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SLG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_slgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( SLGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_s( Register r1, const Address& a) { z_s( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_sy( Register r1, const Address& a) { z_sy( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_sl( Register r1, const Address& a) { z_sl( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_sly( Register r1, const Address& a) { z_sly( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_sg( Register r1, const Address& a) { z_sg( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_sgf( Register r1, const Address& a) { z_sgf( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_slg( Register r1, const Address& a) { z_slg( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -533,8 +568,8 @@ inline void Assembler::z_sgfr(Register r1, Register r2) { emit_32( SGFR_ZOPC | r inline void Assembler::z_srk( Register r1, Register r2, Register r3) { emit_32( SRK_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | reg(r3, 16, 32)); } inline void Assembler::z_sgrk(Register r1, Register r2, Register r3) { emit_32( SGRK_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32) | reg(r3, 16, 32)); } -inline void Assembler::z_sh( Register r1, int64_t d2, Register x2, Register b2) { emit_32( SH_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_shy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SHY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_sh( Register r1, int64_t d2, Register x2, Register b2) { emit_32( SH_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_shy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( SHY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_sh( Register r1, const Address &a) { z_sh( r1, a.disp(), a.indexOrR0(), a.base()); } inline void Assembler::z_shy( Register r1, const Address &a) { z_shy(r1, a.disp(), a.indexOrR0(), a.base()); } @@ -560,12 +595,12 @@ inline void Assembler::z_msgfr(Register r1, Register r2) { emit_32( MSGFR_ZOPC | inline void Assembler::z_mlr( Register r1, Register r2) { emit_32( MLR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_mlgr( Register r1, Register r2) { emit_32( MLGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_mhy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MHY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_msy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_msg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_msgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSGF_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ml( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ML_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_mlg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_mhy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MHY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_msy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_msg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_msgf(Register r1, int64_t d2, Register x2, Register b2) { emit_48( MSGF_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ml( Register r1, int64_t d2, Register x2, Register b2) { emit_48( ML_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_mlg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( MLG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_mhy( Register r1, const Address& a) { z_mhy( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_msy( Register r1, const Address& a) { z_msy( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -583,45 +618,44 @@ inline void Assembler::z_mghi( Register r1, int64_t i2) { emit_32( MGHI_ZOPC | //------------------ // DIVIDE //------------------ -inline void Assembler::z_dsgr( Register r1, Register r2) { emit_32( DSGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_dsgr( Register r1, Register r2) { emit_32( DSGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_dsgfr(Register r1, Register r2) { emit_32( DSGFR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } //------------------- // COMPARE //------------------- -inline void Assembler::z_cr( Register r1, Register r2) { emit_16( CR_ZOPC | reg(r1, 8, 16) | reg(r2,12,16)); } +inline void Assembler::z_cr( Register r1, Register r2) { emit_16( CR_ZOPC | reg(r1, 8, 16) | reg(r2, 12, 16)); } +inline void Assembler::z_clr( Register r1, Register r2) { emit_16( CLR_ZOPC | reg(r1, 8, 16) | reg(r2, 12, 16)); } inline void Assembler::z_cgr( Register r1, Register r2) { emit_32( CGR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_cgfr(Register r1, Register r2) { emit_32( CGFR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_clgr(Register r1, Register r2) { emit_32( CLGR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_chi( Register r1, int64_t i2) { emit_32( CHI_ZOPC | reg(r1, 8, 32) | simm16(i2, 16, 32)); } inline void Assembler::z_cghi(Register r1, int64_t i2) { emit_32( CGHI_ZOPC | reg(r1, 8, 32) | simm16(i2, 16, 32)); } inline void Assembler::z_cfi( Register r1, int64_t i2) { emit_48( CFI_ZOPC | regt(r1, 8, 48) | uimm32(i2, 16, 48)); } inline void Assembler::z_cgfi(Register r1, int64_t i2) { emit_48( CGFI_ZOPC | regt(r1, 8, 48) | uimm32(i2, 16, 48)); } -inline void Assembler::z_ch(Register r1, const Address &a) { z_ch(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ch(Register r1, int64_t d2, Register x2, Register b2) { emit_32( CH_ZOPC | reg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_c(Register r1, const Address &a) { z_c(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_c(Register r1, int64_t d2, Register x2, Register b2) { emit_32( C_ZOPC | reg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_cy(Register r1, const Address &a) { z_cy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_cy(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_cy(Register r1, int64_t d2, Register b2) { z_cy(r1, d2, Z_R0, b2); } -inline void Assembler::z_cg(Register r1, const Address &a) { z_cg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_cg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CG_ZOPC | reg(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_clr(Register r1, Register r2) { emit_16( CLR_ZOPC | reg(r1,8,16) | reg(r2,12,16)); } -inline void Assembler::z_clgr(Register r1, Register r2) { emit_32( CLGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); } - - -inline void Assembler::z_clfi(Register r1, int64_t i2) { emit_48( CLFI_ZOPC | regt(r1, 8, 48) | uimm32(i2, 16, 48)); } +inline void Assembler::z_ch( Register r1, int64_t d2, Register x2, Register b2) { emit_32( CH_ZOPC | reg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_c( Register r1, int64_t d2, Register x2, Register b2) { emit_32( C_ZOPC | reg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_cy( Register r1, int64_t d2, Register x2, Register b2) { emit_48( CY_ZOPC | reg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_cg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( CG_ZOPC | reg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ch( Register r1, const Address &a) { z_ch(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_c( Register r1, const Address &a) { z_c( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_cy( Register r1, const Address &a) { z_cy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_cg( Register r1, const Address &a) { z_cg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } + + +inline void Assembler::z_clfi( Register r1, int64_t i2) { emit_48( CLFI_ZOPC | regt(r1, 8, 48) | uimm32(i2, 16, 48)); } inline void Assembler::z_clgfi(Register r1, int64_t i2) { emit_48( CLGFI_ZOPC | regt(r1, 8, 48) | uimm32(i2, 16, 48)); } -inline void Assembler::z_cl(Register r1, const Address &a) { z_cl(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_cl(Register r1, int64_t d2, Register x2, Register b2) { emit_32( CL_ZOPC | regt(r1, 8, 32) | uimm12(d2,20,32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_cly(Register r1, const Address &a) { z_cly(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_cly(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CLY_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_cly(Register r1, int64_t d2, Register b2) { z_cly(r1, d2, Z_R0, b2); } -inline void Assembler::z_clg(Register r1, const Address &a) { z_clg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_clg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CLG_ZOPC | reg(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_clc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( CLC_ZOPC | uimm12(d1, 20, 48) | uimm8(l, 8, 48) | regz(b1, 16, 48) | uimm12(d2, 36, 48) | regz(b2, 32, 48)); } -inline void Assembler::z_clcle(Register r1, Register r3, int64_t d2, Register b2) { emit_32( CLCLE_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } -inline void Assembler::z_clclu(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CLCLU_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | uimm12(d2, 20, 48) | reg(b2, 16, 48)); } +inline void Assembler::z_cl( Register r1, int64_t d2, Register x2, Register b2) { emit_32( CL_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_cly( Register r1, int64_t d2, Register x2, Register b2) { emit_48( CLY_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_clg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( CLG_ZOPC | reg( r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_cl( Register r1, const Address &a) { z_cl( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_cly( Register r1, const Address &a) { z_cly(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_clg( Register r1, const Address &a) { z_clg(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } + +inline void Assembler::z_clc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2) { emit_48( CLC_ZOPC | uimm8(l, 8, 48) | rsmask_48(d1, b1) | rsmask_SS(d2, b2)); } +inline void Assembler::z_clcle(Register r1, Register r3, int64_t d2, Register b2) { emit_32( CLCLE_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | rsmaskt_32( d2, b2)); } +inline void Assembler::z_clclu(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CLCLU_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | rsymaskt_48(d2, b2)); } inline void Assembler::z_tmll(Register r1, int64_t i2) { emit_32( TMLL_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } inline void Assembler::z_tmlh(Register r1, int64_t i2) { emit_32( TMLH_ZOPC | regt(r1, 8, 32) | imm16(i2, 16, 32)); } @@ -634,86 +668,89 @@ inline void Assembler::z_trot(Register r1, Register r2, int64_t m3) { emit_32( T inline void Assembler::z_trto(Register r1, Register r2, int64_t m3) { emit_32( TRTO_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } inline void Assembler::z_trtt(Register r1, Register r2, int64_t m3) { emit_32( TRTT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } + +//------------------------ +// COMPARE AND BRANCH/TRAP +//------------------------ // signed comparison -inline void Assembler::z_crb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_cgrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CGRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_crj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_cgrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CGRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_cib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | simm8(i2, 32, 48)); } -inline void Assembler::z_cgib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CGIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | simm8(i2, 32, 48)); } -inline void Assembler::z_cij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | simm8(i2, 32, 48)); } -inline void Assembler::z_cgij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CGIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | simm8(i2, 32, 48)); } +inline void Assembler::z_crb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | rsmask_48(d4, b4) | uimm4(m3, 32, 48)); } +inline void Assembler::z_cgrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CGRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | rsmask_48(d4, b4) | uimm4(m3, 32, 48)); } +inline void Assembler::z_crj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } +inline void Assembler::z_cgrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CGRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } +inline void Assembler::z_cib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | rsmask_48(d4, b4) | simm8(i2, 32, 48)); } +inline void Assembler::z_cgib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CGIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | rsmask_48(d4, b4) | simm8(i2, 32, 48)); } +inline void Assembler::z_cij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | simm8(i2, 32, 48)); } +inline void Assembler::z_cgij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CGIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | simm8(i2, 32, 48)); } // unsigned comparison -inline void Assembler::z_clrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_clgrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLGRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_clrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CLRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_clgrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CLGRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_clib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm8(i2, 32, 48)); } -inline void Assembler::z_clgib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLGIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | uimm12(d4, 20, 48) | reg(b4, 16, 48) | uimm8(i2, 32, 48)); } -inline void Assembler::z_clij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CLIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm8(i2, 32, 48)); } +inline void Assembler::z_clrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | rsmask_48(d4, b4) | uimm4(m3, 32, 48)); } +inline void Assembler::z_clgrb(Register r1, Register r2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLGRB_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | rsmask_48(d4, b4) | uimm4(m3, 32, 48)); } +inline void Assembler::z_clrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CLRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } +inline void Assembler::z_clgrj(Register r1, Register r2, branch_condition m3, address a4) { emit_48( CLGRJ_ZOPC | reg(r1, 8, 48) | reg(r2, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm4(m3, 32, 48)); } +inline void Assembler::z_clib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | rsmask_48(d4, b4) | uimm8(i2, 32, 48)); } +inline void Assembler::z_clgib(Register r1, int64_t i2, branch_condition m3, int64_t d4, Register b4) { emit_48( CLGIB_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | rsmask_48(d4, b4) | uimm8(i2, 32, 48)); } +inline void Assembler::z_clij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CLIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm8(i2, 32, 48)); } inline void Assembler::z_clgij(Register r1, int64_t i2, branch_condition m3, address a4) { emit_48( CLGIJ_ZOPC | reg(r1, 8, 48) | uimm4(m3, 12, 48) | simm16(RelAddr::pcrel_off16(a4, pc()), 16, 48) | uimm8(i2, 32, 48)); } // Compare and trap instructions (signed). -inline void Assembler::z_crt(Register r1, Register r2, int64_t m3) { emit_32( CRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } -inline void Assembler::z_cgrt(Register r1, Register r2, int64_t m3) { emit_32( CGRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } +inline void Assembler::z_crt(Register r1, Register r2, int64_t m3) { emit_32( CRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } +inline void Assembler::z_cgrt(Register r1, Register r2, int64_t m3) { emit_32( CGRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } inline void Assembler::z_cit(Register r1, int64_t i2, int64_t m3) { emit_48( CIT_ZOPC | reg(r1, 8, 48) | simm16(i2, 16, 48) | uimm4(m3, 32, 48)); } inline void Assembler::z_cgit(Register r1, int64_t i2, int64_t m3) { emit_48( CGIT_ZOPC | reg(r1, 8, 48) | simm16(i2, 16, 48) | uimm4(m3, 32, 48)); } // Compare and trap instructions (unsigned). -inline void Assembler::z_clrt(Register r1, Register r2, int64_t m3) { emit_32( CLRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } -inline void Assembler::z_clgrt(Register r1, Register r2, int64_t m3) { emit_32( CLGRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } +inline void Assembler::z_clrt(Register r1, Register r2, int64_t m3) { emit_32( CLRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } +inline void Assembler::z_clgrt(Register r1, Register r2, int64_t m3) { emit_32( CLGRT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } inline void Assembler::z_clfit(Register r1, int64_t i2, int64_t m3) { emit_48( CLFIT_ZOPC | reg(r1, 8, 48) | uimm16(i2, 16, 48) | uimm4(m3, 32, 48)); } inline void Assembler::z_clgit(Register r1, int64_t i2, int64_t m3) { emit_48( CLGIT_ZOPC | reg(r1, 8, 48) | uimm16(i2, 16, 48) | uimm4(m3, 32, 48)); } -inline void Assembler::z_bc( branch_condition m1, int64_t d2, Register x2, Register b2) { emit_32( BC_ZOPC | 0 << 16 | uimm4(m1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_bcr( branch_condition m1, Register r2) { emit_16( BCR_ZOPC | uimm4(m1,8,16) | reg(r2,12,16)); } -inline void Assembler::z_brc( branch_condition i1, int64_t i2) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(i2, 16, 32)); } -inline void Assembler::z_brc( branch_condition i1, address a) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32)); } -inline void Assembler::z_brcl(branch_condition i1, address a) { emit_48( BRCL_ZOPC | uimm4(i1, 8, 48)| simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } -inline void Assembler::z_bctgr(Register r1, Register r2) { emit_32( BCTGR_ZOPC | reg( r1, 24, 32) | reg( r2, 28, 32)); }; -inline void Assembler::z_basr(Register r1, Register r2) { emit_16( BASR_ZOPC | regt(r1,8,16) | reg(r2,12,16)); } - -inline void Assembler::z_brasl(Register r1, address a) { emit_48( BRASL_ZOPC | regt(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } - -inline void Assembler::z_brct(Register r1, address a) { emit_32( BRCT_ZOPC | regt(r1, 8, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32)); } -inline void Assembler::z_brct(Register r1, Label& L) {z_brct(r1, target(L)); } +//------------------------ +// BRANCH/CALL +//------------------------ +inline void Assembler::z_bc( branch_condition m1, int64_t d2, Register x2, Register b2) { emit_32( BC_ZOPC | uimm4(m1, 8, 32) | rxmask_32(d2, x2, b2)); } +inline void Assembler::z_bcr( branch_condition m1, Register r2) { emit_16( BCR_ZOPC | uimm4(m1, 8, 16) | reg(r2, 12, 16)); } +inline void Assembler::z_brc( branch_condition i1, int64_t i2) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(i2, 16, 32)); } +inline void Assembler::z_brc( branch_condition i1, address a) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32)); } +inline void Assembler::z_brcl(branch_condition i1, address a) { emit_48( BRCL_ZOPC | uimm4(i1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } +inline void Assembler::z_bctgr(Register r1, Register r2) { emit_32( BCTGR_ZOPC | reg( r1, 24, 32) | reg( r2, 28, 32)); }; -inline void Assembler::z_brxh(Register r1, Register r3, address a) {emit_32( BRXH_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32));} -inline void Assembler::z_brxh(Register r1, Register r3, Label& L) {z_brxh(r1, r3, target(L)); } +inline void Assembler::z_basr( Register r1, Register r2) { emit_16( BASR_ZOPC | regt(r1, 8, 16) | reg(r2, 12, 16)); } +inline void Assembler::z_brasl(Register r1, address a) { emit_48( BRASL_ZOPC | regt(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } +inline void Assembler::z_brct(Register r1, address a) {emit_32( BRCT_ZOPC | reg(r1, 8, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32)); } +inline void Assembler::z_brxh(Register r1, Register r3, address a) {emit_32( BRXH_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32));} inline void Assembler::z_brxle(Register r1, Register r3, address a) {emit_32( BRXLE_ZOPC | reg(r1, 8, 32) | reg(r3, 12, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32));} -inline void Assembler::z_brxle(Register r1, Register r3, Label& L) {z_brxle(r1, r3, target(L)); } - inline void Assembler::z_brxhg(Register r1, Register r3, address a) {emit_48( BRXHG_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 48));} -inline void Assembler::z_brxhg(Register r1, Register r3, Label& L) {z_brxhg(r1, r3, target(L)); } - inline void Assembler::z_brxlg(Register r1, Register r3, address a) {emit_48( BRXLG_ZOPC | reg(r1, 8, 48) | reg(r3, 12, 48) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 48));} +inline void Assembler::z_brct(Register r1, Label& L) {z_brct( r1, target(L)); } +inline void Assembler::z_brxh(Register r1, Register r3, Label& L) {z_brxh( r1, r3, target(L)); } +inline void Assembler::z_brxle(Register r1, Register r3, Label& L) {z_brxle(r1, r3, target(L)); } +inline void Assembler::z_brxhg(Register r1, Register r3, Label& L) {z_brxhg(r1, r3, target(L)); } inline void Assembler::z_brxlg(Register r1, Register r3, Label& L) {z_brxlg(r1, r3, target(L)); } -inline void Assembler::z_flogr(Register r1, Register r2) { emit_32( FLOGR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_popcnt(Register r1, Register r2) { emit_32( POPCNT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_ahhhr(Register r1, Register r2, Register r3) { emit_32( AHHHR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_ahhlr(Register r1, Register r2, Register r3) { emit_32( AHHLR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_flogr( Register r1, Register r2) { emit_32( FLOGR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_popcnt(Register r1, Register r2) { emit_32( POPCNT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_ahhhr( Register r1, Register r2, Register r3) { emit_32( AHHHR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_ahhlr( Register r1, Register r2, Register r3) { emit_32( AHHLR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_tam() { emit_16( TAM_ZOPC); } -inline void Assembler::z_stckf(int64_t d2, Register b2) { emit_32( STCKF_ZOPC | uimm12(d2, 20, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( STM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); } -inline void Assembler::z_stmy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } -inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } -inline void Assembler::z_lm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( LM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); } -inline void Assembler::z_lmy( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } -inline void Assembler::z_lmg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } - -inline void Assembler::z_cs( Register r1, Register r3, int64_t d2, Register b2) { emit_32( CS_ZOPC | regt(r1, 8, 32) | reg(r3, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); } -inline void Assembler::z_csy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSY_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); } -inline void Assembler::z_csg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); } +inline void Assembler::z_stckf(int64_t d2, Register b2) { emit_32( STCKF_ZOPC | rsmask_32(d2, b2)); } +inline void Assembler::z_stm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( STM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| rsmask_32( d2, b2)); } +inline void Assembler::z_stmy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| rsymask_48(d2, b2)); } +inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| rsymask_48(d2, b2)); } +inline void Assembler::z_lm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( LM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| rsmask_32( d2, b2)); } +inline void Assembler::z_lmy( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| rsymask_48(d2, b2)); } +inline void Assembler::z_lmg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| rsymask_48(d2, b2)); } + +inline void Assembler::z_cs( Register r1, Register r3, int64_t d2, Register b2) { emit_32( CS_ZOPC | regt(r1, 8, 32) | reg(r3, 12, 32) | rsmask_32( d2, b2)); } +inline void Assembler::z_csy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSY_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } +inline void Assembler::z_csg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | rsymask_48(d2, b2)); } inline void Assembler::z_cs( Register r1, Register r3, const Address& a) { assert(!a.has_index(), "Cannot encode index"); z_cs( r1, r3, a.disp(), a.baseOrR0()); } inline void Assembler::z_csy(Register r1, Register r3, const Address& a) { assert(!a.has_index(), "Cannot encode index"); z_csy(r1, r3, a.disp(), a.baseOrR0()); } inline void Assembler::z_csg(Register r1, Register r3, const Address& a) { assert(!a.has_index(), "Cannot encode index"); z_csg(r1, r3, a.disp(), a.baseOrR0()); } -inline void Assembler::z_cvd(Register r1, int64_t d2, Register x2, Register b2) { emit_32( CVD_ZOPC | regt(r1, 8, 32) | reg(x2, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); } -inline void Assembler::z_cvdg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CVDG_ZOPC | regt(r1, 8, 48) | reg(x2, 12, 48) | reg(b2, 16, 48) | simm20(d2)); } +inline void Assembler::z_cvd( Register r1, int64_t d2, Register x2, Register b2) { emit_32( CVD_ZOPC | regt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_cvdg(Register r1, int64_t d2, Register x2, Register b2) { emit_48( CVDG_ZOPC | regt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } //--------------------------- @@ -1142,30 +1179,30 @@ inline void Assembler::z_ler( FloatRegister r1, FloatRegister r2) { emit_16( LE inline void Assembler::z_ldr( FloatRegister r1, FloatRegister r2) { emit_16( LDR_ZOPC | fregt(r1,8,16) | freg(r2,12,16)); } inline void Assembler::z_ldebr(FloatRegister r1, FloatRegister r2) { emit_32( LDEBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } inline void Assembler::z_ledbr(FloatRegister r1, FloatRegister r2) { emit_32( LEDBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } -inline void Assembler::z_le( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( LE_ZOPC | fregt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_ley(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( LEY_ZOPC | fregt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ld( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( LD_ZOPC | fregt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_ldy(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( LDY_ZOPC | fregt(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_le( FloatRegister r1, const Address &a) { z_le( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ley(FloatRegister r1, const Address &a) { z_ley(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ld( FloatRegister r1, const Address &a) { z_ld( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ldy(FloatRegister r1, const Address &a) { z_ldy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_le( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( LE_ZOPC | fregt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_ley( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( LEY_ZOPC | fregt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ld( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( LD_ZOPC | fregt(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_ldy( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( LDY_ZOPC | fregt(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_le( FloatRegister r1, const Address &a) { z_le( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ley( FloatRegister r1, const Address &a) { z_ley(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ld( FloatRegister r1, const Address &a) { z_ld( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ldy( FloatRegister r1, const Address &a) { z_ldy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_lzdr(FloatRegister r1) { emit_32( LZDR_ZOPC | fregt(r1, 24, 32)); } -inline void Assembler::z_lzer(FloatRegister f1) { emit_32( LZER_ZOPC | fregt(f1, 24, 32)); } +inline void Assembler::z_lzdr( FloatRegister r1) { emit_32( LZDR_ZOPC | fregt(r1, 24, 32)); } +inline void Assembler::z_lzer( FloatRegister f1) { emit_32( LZER_ZOPC | fregt(f1, 24, 32)); } //----------------- // STORE //----------------- -inline void Assembler::z_ste( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( STE_ZOPC | freg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stey(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( STEY_ZOPC | freg(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_std( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( STD_ZOPC | freg(r1, 8, 32) | uimm12(d2, 20, 32) | reg(x2, 12, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stdy(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( STDY_ZOPC | freg(r1, 8, 48) | simm20(d2) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ste( FloatRegister r1, const Address &a) { z_ste( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_stey(FloatRegister r1, const Address &a) { z_stey(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_std( FloatRegister r1, const Address &a) { z_std( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_stdy(FloatRegister r1, const Address &a) { z_stdy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ste( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( STE_ZOPC | freg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_stey( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( STEY_ZOPC | freg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_std( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_32( STD_ZOPC | freg(r1, 8, 32) | rxmask_32( d2, x2, b2)); } +inline void Assembler::z_stdy( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( STDY_ZOPC | freg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } +inline void Assembler::z_ste( FloatRegister r1, const Address &a) { z_ste( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_stey( FloatRegister r1, const Address &a) { z_stey(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_std( FloatRegister r1, const Address &a) { z_std( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_stdy( FloatRegister r1, const Address &a) { z_stdy(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } //--------------- @@ -1173,35 +1210,34 @@ inline void Assembler::z_stdy(FloatRegister r1, const Address &a) { z_stdy(r1, a //--------------- inline void Assembler::z_aebr( FloatRegister f1, FloatRegister f2) { emit_32( AEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} inline void Assembler::z_adbr( FloatRegister f1, FloatRegister f2) { emit_32( ADBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_aeb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( AEB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_adb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( ADB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_aeb( FloatRegister r1, const Address& a) { z_aeb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_adb( FloatRegister r1, const Address& a) { z_adb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_aeb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( AEB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_adb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( ADB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_aeb( FloatRegister r1, const Address& a) { z_aeb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_adb( FloatRegister r1, const Address& a) { z_adb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } //--------------- // SUB //--------------- -inline void Assembler::z_sebr( FloatRegister f1, FloatRegister f2) { emit_32( SEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_sdbr( FloatRegister f1, FloatRegister f2) { emit_32( SDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_seb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( SEB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_sdb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( SDB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} +inline void Assembler::z_sebr( FloatRegister f1, FloatRegister f2) { emit_32( SEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_sdbr( FloatRegister f1, FloatRegister f2) { emit_32( SDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_seb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( SEB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_sdb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( SDB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} inline void Assembler::z_seb( FloatRegister r1, const Address& a) { z_seb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_sdb( FloatRegister r1, const Address& a) { z_sdb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_lcebr(FloatRegister r1, FloatRegister r2) { emit_32( LCEBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } inline void Assembler::z_lcdbr(FloatRegister r1, FloatRegister r2) { emit_32( LCDBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } - -inline void Assembler::z_lpdbr( FloatRegister fr1, FloatRegister fr2) { emit_32( LPDBR_ZOPC | fregt( fr1, 24,32) | freg((fr2 == fnoreg) ? fr1:fr2, 28, 32)); } +inline void Assembler::z_lpdbr(FloatRegister r1, FloatRegister r2) { emit_32( LPDBR_ZOPC | fregt(r1, 24, 32) | freg((r2 == fnoreg) ? r1:r2, 28, 32)); } //--------------- // MUL //--------------- -inline void Assembler::z_meebr(FloatRegister f1, FloatRegister f2) { emit_32( MEEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_mdbr( FloatRegister f1, FloatRegister f2) { emit_32( MDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_meeb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( MEEB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_mdb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( MDB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} +inline void Assembler::z_meebr(FloatRegister f1, FloatRegister f2) { emit_32( MEEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_mdbr( FloatRegister f1, FloatRegister f2) { emit_32( MDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_meeb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( MEEB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_mdb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( MDB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} inline void Assembler::z_meeb( FloatRegister r1, const Address& a) { z_meeb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_mdb( FloatRegister r1, const Address& a) { z_mdb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -1213,43 +1249,43 @@ inline void Assembler::z_maebr(FloatRegister f1, FloatRegister f3, FloatRegister inline void Assembler::z_madbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MADBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );} inline void Assembler::z_msebr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSEBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );} inline void Assembler::z_msdbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSDBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );} -inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MAEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );} -inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MADB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );} -inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );} -inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSDB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );} -inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, const Address& a) { z_maeb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, const Address& a) { z_madb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, const Address& a) { z_mseb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, const Address& a) { z_msdb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MAEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | rxmask_48(d2, x2, b2) );} +inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MADB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | rxmask_48(d2, x2, b2) );} +inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | rxmask_48(d2, x2, b2) );} +inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSDB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | rxmask_48(d2, x2, b2) );} +inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, const Address& a) { z_maeb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, const Address& a) { z_madb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, const Address& a) { z_mseb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, const Address& a) { z_msdb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); } //--------------- // DIV //--------------- -inline void Assembler::z_debr( FloatRegister f1, FloatRegister f2) { emit_32( DEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_ddbr( FloatRegister f1, FloatRegister f2) { emit_32( DDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} -inline void Assembler::z_deb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( DEB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_ddb( FloatRegister f1, int64_t d2, Register x2, Register b2 ) { emit_48( DDB_ZOPC | fregt( f1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_deb( FloatRegister r1, const Address& a) { z_deb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } -inline void Assembler::z_ddb( FloatRegister r1, const Address& a) { z_ddb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_debr( FloatRegister f1, FloatRegister f2) { emit_32( DEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_ddbr( FloatRegister f1, FloatRegister f2) { emit_32( DDBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));} +inline void Assembler::z_deb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( DEB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_ddb( FloatRegister f1, int64_t d2, Register x2, Register b2) { emit_48( DDB_ZOPC | fregt( f1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_deb( FloatRegister r1, const Address& a) { z_deb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_ddb( FloatRegister r1, const Address& a) { z_ddb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } //--------------- // square root //--------------- -inline void Assembler::z_sqdbr(FloatRegister f1, FloatRegister f2) { emit_32(SQDBR_ZOPC | fregt(f1, 24, 32) | freg(f2, 28, 32)); } -inline void Assembler::z_sqdb( FloatRegister fr1, int64_t d2, Register x2, Register b2 ) { emit_48( SQDB_ZOPC | fregt( fr1, 8, 48) | uimm12( d2, 20, 48) | reg( x2, 12, 48) | regz( b2, 16, 48));} -inline void Assembler::z_sqdb( FloatRegister fr1, int64_t d2, Register b2) { z_sqdb( fr1, d2, Z_R0, b2);} +inline void Assembler::z_sqdbr(FloatRegister r1, FloatRegister r2) { emit_32(SQDBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } +inline void Assembler::z_sqdb( FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( SQDB_ZOPC | fregt( r1, 8, 48) | rxmask_48(d2, x2, b2));} +inline void Assembler::z_sqdb( FloatRegister r1, int64_t d2, Register b2) { z_sqdb( r1, d2, Z_R0, b2);} //--------------- // CMP //--------------- inline void Assembler::z_cebr(FloatRegister r1, FloatRegister r2) { emit_32( CEBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } -inline void Assembler::z_ceb(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( CEB_ZOPC | fregt(r1, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48)); } -inline void Assembler::z_ceb(FloatRegister r1, const Address &a) { z_ceb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_cdbr(FloatRegister r1, FloatRegister r2) { emit_32( CDBR_ZOPC | fregt(r1, 24, 32) | freg(r2, 28, 32)); } -inline void Assembler::z_cdb(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( CDB_ZOPC | fregt(r1, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48)); } +inline void Assembler::z_ceb(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( CEB_ZOPC | fregt(r1, 8, 48) | rxmask_48(d2, x2, b2)); } +inline void Assembler::z_cdb(FloatRegister r1, int64_t d2, Register x2, Register b2) { emit_48( CDB_ZOPC | fregt(r1, 8, 48) | rxmask_48(d2, x2, b2)); } +inline void Assembler::z_ceb(FloatRegister r1, const Address &a) { z_ceb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } inline void Assembler::z_cdb(FloatRegister r1, const Address &a) { z_cdb(r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } @@ -1280,13 +1316,16 @@ inline void Assembler::z_cgdbr(Register r1, FloatRegister r2, RoundingMode m) { inline void Assembler::z_st(Register r1, int64_t d2, Register b2) { z_st( r1, d2, Z_R0, b2); } inline void Assembler::z_sty(Register r1, int64_t d2, Register b2) { z_sty( r1, d2, Z_R0, b2); } inline void Assembler::z_stg(Register r1, int64_t d2, Register b2) { z_stg( r1, d2, Z_R0, b2); } - inline void Assembler::z_lgf(Register r1, int64_t d2, Register b2) { z_lgf( r1, d2, Z_R0, b2); } + inline void Assembler::z_lgb(Register r1, int64_t d2, Register b2) { z_lgb( r1, d2, Z_R0, b2); } inline void Assembler::z_lgh(Register r1, int64_t d2, Register b2) { z_lgh( r1, d2, Z_R0, b2); } + inline void Assembler::z_lgf(Register r1, int64_t d2, Register b2) { z_lgf( r1, d2, Z_R0, b2); } + inline void Assembler::z_llgc(Register r1, int64_t d2, Register b2) { z_llgc(r1, d2, Z_R0, b2); } inline void Assembler::z_llgh(Register r1, int64_t d2, Register b2) { z_llgh(r1, d2, Z_R0, b2); } inline void Assembler::z_llgf(Register r1, int64_t d2, Register b2) { z_llgf(r1, d2, Z_R0, b2); } - inline void Assembler::z_lgb(Register r1, int64_t d2, Register b2) { z_lgb( r1, d2, Z_R0, b2); } inline void Assembler::z_cl( Register r1, int64_t d2, Register b2) { z_cl( r1, d2, Z_R0, b2); } - inline void Assembler::z_c(Register r1, int64_t d2, Register b2) { z_c( r1, d2, Z_R0, b2); } + inline void Assembler::z_cly(Register r1, int64_t d2, Register b2) { z_cly( r1, d2, Z_R0, b2); } + inline void Assembler::z_c( Register r1, int64_t d2, Register b2) { z_c( r1, d2, Z_R0, b2); } + inline void Assembler::z_cy(Register r1, int64_t d2, Register b2) { z_cy( r1, d2, Z_R0, b2); } inline void Assembler::z_cg(Register r1, int64_t d2, Register b2) { z_cg( r1, d2, Z_R0, b2); } inline void Assembler::z_sh(Register r1, int64_t d2, Register b2) { z_sh( r1, d2, Z_R0, b2); } inline void Assembler::z_shy(Register r1, int64_t d2, Register b2) { z_shy( r1, d2, Z_R0, b2); } @@ -1346,24 +1385,40 @@ inline void Assembler::z_brc( branch_condition m, Label& L) { z_brc(m, target(L) inline void Assembler::z_brcl(branch_condition m, Label& L) { z_brcl(m, target(L)); } -// Instruction must start at passed address. -// Extra check for illtraps with ID. -inline unsigned int Assembler::instr_len(unsigned char *instr) { - switch ((*instr) >> 6) { +// Instruction len bits must be stored right-justified in argument. +inline unsigned int Assembler::instr_len(unsigned char len_bits) { + assert(len_bits < 4, "bad instruction len %d", len_bits); + switch (len_bits) { case 0: return 2; case 1: // fallthru case 2: return 4; case 3: return 6; default: - // Control can't reach here. - // The switch expression examines just the leftmost two bytes + // len_bits contains, right-justified, only the leftmost two bits // of the main opcode. So the range of values is just [0..3]. - // Having a default clause makes the compiler happy. ShouldNotReachHere(); return 0; } } +// Instruction must start at passed address. +inline unsigned int Assembler::instr_len(unsigned char *instr) { + return instr_len((unsigned char)((*instr) >> 6)); +} + +// Instruction must be stored right-justified in argument. +inline unsigned int Assembler::instr_len(unsigned long instr) { + // An instruction is 2, 4, or 6 bytes in length. + // The instruction length in encoded in the leftmost two bits of the instruction. + // len = 6: len_bits = [46..47] + // len = 4: len_bits = [30..31] + // len = 2: len_bits = [14..15] + unsigned char len_bits = instr >> (48-2); + if (len_bits == 0) len_bits = instr >> (32-2); + if (len_bits == 0) len_bits = instr >> (16-2); + return instr_len(len_bits); +} + // Move instr at pc right-justified into passed long int. // Return instr len in bytes as function result. // Note: 2-byte instr don't really need to be accessed unsigned @@ -1383,9 +1438,7 @@ inline unsigned int Assembler::get_instruction(unsigned char *pc, unsigned long *instr = ((unsigned long)(*(unsigned int*) pc)) << 16 | ((unsigned long)*(unsigned short*) (pc + 4)); break; default: - // Control can't reach here. // The length as returned from instr_len() can only be 2, 4, or 6 bytes. - // Having a default clause makes the compiler happy. ShouldNotReachHere(); *instr = 0L; // This assignment is there to make gcc8 happy. break; diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 1d1f163826e243de60c85a19890b5191a1140bee..efa142332ef9defe0279baad901f38524eaee693 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.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. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1440,7 +1440,10 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op } // result = condition ? opr1 : opr2 -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on s390"); + Assembler::branch_condition acond = Assembler::bcondEqual, ncond = Assembler::bcondNotEqual; switch (condition) { case lir_cond_equal: acond = Assembler::bcondEqual; ncond = Assembler::bcondNotEqual; break; 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..f603c5fa00a44caa0c29141bd253de372b2e76b1 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -697,27 +697,18 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { } static inline void z_emit16(CodeBuffer &cbuf, long value) { - // 32bit instructions may become sign extended. - assert(value >= 0, "unintended sign extension (int->long)"); - assert(value < (1L << 16), "instruction too large"); - *((unsigned short*)(cbuf.insts_end())) = (unsigned short)value; - cbuf.set_insts_end(cbuf.insts_end() + sizeof(unsigned short)); + C2_MacroAssembler _masm(&cbuf); + __ emit_instruction((unsigned long)value, 2); } static inline void z_emit32(CodeBuffer &cbuf, long value) { - // 32bit instructions may become sign extended. - assert(value < (1L << 32), "instruction too large"); - *((unsigned int*)(cbuf.insts_end())) = (unsigned int)value; - cbuf.set_insts_end(cbuf.insts_end() + sizeof(unsigned int)); + C2_MacroAssembler _masm(&cbuf); + __ emit_instruction((unsigned long)value, 4); } static inline void z_emit48(CodeBuffer &cbuf, long value) { - // 32bit instructions may become sign extended. - assert(value >= 0, "unintended sign extension (int->long)"); - assert(value < (1L << 48), "instruction too large"); - value = value<<16; - memcpy(cbuf.insts_end(), (unsigned char*)&value, 6); - cbuf.set_insts_end(cbuf.insts_end() + 6); + C2_MacroAssembler _masm(&cbuf); + __ emit_instruction((unsigned long)value, 6); } static inline unsigned int z_emit_inst(CodeBuffer &cbuf, long value) { @@ -726,19 +717,9 @@ static inline unsigned int z_emit_inst(CodeBuffer &cbuf, long value) { value = (long)((unsigned long)((unsigned int)value)); } - if (value < (1L << 16)) { // 2-byte instruction - z_emit16(cbuf, value); - return 2; - } - - if (value < (1L << 32)) { // 4-byte instruction, might be unaligned store - z_emit32(cbuf, value); - return 4; - } - - // 6-byte instruction, probably unaligned store. - z_emit48(cbuf, value); - return 6; + C2_MacroAssembler _masm(&cbuf); + int len = __ emit_instruction((unsigned long)value, 0); + return len; } // Check effective address (at runtime) for required alignment. @@ -10273,14 +10254,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/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index 102200fc08f3537c894a88e91b20b0a2d511e9b3..21cf227067b9d3619ccfbf0ad67ca9261f32d8f0 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -2419,9 +2419,9 @@ class StubGenerator: public StubCodeGenerator { // Put extra information in the stub code, to make it more readable. // Write the high part of the address. // [RGV] Check if there is a dependency on the size of this prolog. - __ emit_32((intptr_t)cdesc >> 32); - __ emit_32((intptr_t)cdesc); - __ emit_32(++_stub_count); + __ emit_data((intptr_t)cdesc >> 32); + __ emit_data((intptr_t)cdesc); + __ emit_data(++_stub_count); #endif align(true); } @@ -2435,7 +2435,7 @@ class StubGenerator: public StubCodeGenerator { if (at_header) { while ((intptr_t)(__ pc()) % icache_line_size != 0) { - __ emit_16(0); + __ z_illtrap(); } } else { while ((intptr_t)(__ pc()) % icache_half_line_size != 0) { diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index e9652fa04b24f55e4ed48a4239f860db14aee3b9..fbf95ae02b53ba14803595dd93db0235cba11b00 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); @@ -1974,6 +1995,13 @@ void Assembler::cvttsd2sil(Register dst, XMMRegister src) { emit_int16(0x2C, (0xC0 | encode)); } +void Assembler::cvtss2sil(Register dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); + emit_int16(0x2D, (0xC0 | encode)); +} + void Assembler::cvttss2sil(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -2067,6 +2095,21 @@ void Assembler::vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x5B, (0xC0 | encode)); } +void Assembler::vcvtps2dq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x5B, (0xC0 | encode)); +} + +void Assembler::evcvtpd2qq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(UseAVX > 2 && VM_Version::supports_avx512dq(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x7B, (0xC0 | encode)); +} + void Assembler::evcvtqq2ps(XMMRegister dst, XMMRegister src, int vector_len) { assert(UseAVX > 2 && VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2389,10 +2432,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 +5815,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 +5832,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) { @@ -6450,7 +6515,6 @@ void Assembler::vrndscalepd(XMMRegister dst, Address src, int32_t rmode, int vec emit_int8((rmode)); } - void Assembler::vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionAttr attributes(vector_len, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -8317,8 +8381,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 +9948,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); @@ -12222,6 +12306,13 @@ void Assembler::cvttsd2siq(Register dst, XMMRegister src) { emit_int16(0x2C, (0xC0 | encode)); } +void Assembler::cvtsd2siq(Register dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); + emit_int16(0x2D, (0xC0 | encode)); +} + void Assembler::cvttss2siq(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -12993,6 +13084,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 +13095,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..6af93b52fc639153ab8baf26f14f1a447ae727b7 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); @@ -1152,6 +1149,7 @@ private: void cvtss2sd(XMMRegister dst, Address src); // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer + void cvtsd2siq(Register dst, XMMRegister src); void cvttsd2sil(Register dst, Address src); void cvttsd2sil(Register dst, XMMRegister src); void cvttsd2siq(Register dst, Address src); @@ -1160,6 +1158,7 @@ private: // Convert with Truncation Scalar Single-Precision Floating-Point Value to Doubleword Integer void cvttss2sil(Register dst, XMMRegister src); void cvttss2siq(Register dst, XMMRegister src); + void cvtss2sil(Register dst, XMMRegister src); // Convert vector double to int void cvttpd2dq(XMMRegister dst, XMMRegister src); @@ -1169,6 +1168,7 @@ private: void vcvtpd2ps(XMMRegister dst, XMMRegister src, int vector_len); // Convert vector float and int + void vcvtps2dq(XMMRegister dst, XMMRegister src, int vector_len); void vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len); // Convert vector long to vector FP @@ -1176,6 +1176,7 @@ private: void evcvtqq2pd(XMMRegister dst, XMMRegister src, int vector_len); // Convert vector double to long + void evcvtpd2qq(XMMRegister dst, XMMRegister src, int vector_len); void evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len); // Evex casts with truncation @@ -1933,10 +1934,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 +2100,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/c1_FrameMap_x86.hpp b/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp index a49e2f39a83ad98eacfccd4469aead3ef1d4162f..a9739b1a22b6170adbb35ab38570fe22da3153dd 100644 --- a/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp +++ b/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp @@ -152,14 +152,8 @@ return range; } - static int get_num_caller_save_xmms(void) { - int num_caller_save_xmm_regs = nof_caller_save_xmm_regs; -#ifdef _LP64 - if (UseAVX < 3) { - num_caller_save_xmm_regs = num_caller_save_xmm_regs / 2; - } -#endif - return num_caller_save_xmm_regs; + static int get_num_caller_save_xmms() { + return XMMRegisterImpl::available_xmm_registers(); } static int nof_caller_save_cpu_regs() { return adjust_reg_range(pd_nof_caller_save_cpu_regs_frame_map); } diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index eaeeae235f0d2be6ff8f2adface509258fa9e777..9619a7711e9e811ca3c48c864708c701ef0ff91d 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.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 @@ -2010,7 +2010,10 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { } } -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { + assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on x86"); + Assembler::Condition acond, ncond; switch (condition) { case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; diff --git a/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp b/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp index 8051406617501a49e0c2a1d7512850d62b4a489e..05c8bbdde5fc10a5b15393d67ae73fdd4270eb2f 100644 --- a/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp +++ b/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp @@ -101,12 +101,7 @@ inline void LinearScan::pd_add_temps(LIR_Op* op) { // Implementation of LinearScanWalker inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { - int last_xmm_reg = pd_last_xmm_reg; -#ifdef _LP64 - if (UseAVX < 3) { - last_xmm_reg = pd_first_xmm_reg + (pd_nof_xmm_regs_frame_map / 2) - 1; - } -#endif + int last_xmm_reg = pd_first_xmm_reg + XMMRegisterImpl::available_xmm_registers() - 1; if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) { assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); _first_reg = pd_first_byte_reg; diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index 595e78dc25753a59080df6160514430e8c922925..1bb767994b8524c064c7b8fbc46a1769cada7d79 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/assembler.hpp" #include "c1/c1_Defs.hpp" +#include "c1/c1_FrameMap.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" #include "ci/ciUtilities.hpp" @@ -369,12 +370,7 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next()); #endif // _LP64 - int xmm_bypass_limit = FrameMap::nof_xmm_regs; -#ifdef _LP64 - if (UseAVX < 3) { - xmm_bypass_limit = xmm_bypass_limit / 2; - } -#endif + int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms(); if (save_fpu_registers) { #ifndef _LP64 @@ -487,13 +483,8 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) // so always save them as doubles. // note that float values are _not_ converted automatically, so for float values // the second word contains only garbage data. - int xmm_bypass_limit = FrameMap::nof_xmm_regs; + int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms(); int offset = 0; -#ifdef _LP64 - if (UseAVX < 3) { - xmm_bypass_limit = xmm_bypass_limit / 2; - } -#endif for (int n = 0; n < xmm_bypass_limit; n++) { XMMRegister xmm_name = as_XMMRegister(n); __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name); @@ -513,10 +504,7 @@ static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) { #ifdef _LP64 if (restore_fpu_registers) { // restore XMM registers - int xmm_bypass_limit = FrameMap::nof_xmm_regs; - if (UseAVX < 3) { - xmm_bypass_limit = xmm_bypass_limit / 2; - } + int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms(); int offset = 0; for (int n = 0; n < xmm_bypass_limit; n++) { XMMRegister xmm_name = as_XMMRegister(n); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 400bcec45e2a01ac946c2e84f95e0e56cb6efd77..c4411be23cf76afc3a0cd4d4e1c1052154086b60 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, @@ -4014,41 +4061,18 @@ void C2_MacroAssembler::masked_op(int ideal_opc, int mask_len, KRegister dst, } /* - * Algorithm for vector D2L and F2I conversions:- - * a) Perform vector D2L/F2I cast. - * b) Choose fast path if none of the result vector lane contains 0x80000000 value. - * It signifies that source value could be any of the special floating point - * values(NaN,-Inf,Inf,Max,-Min). - * c) Set destination to zero if source is NaN value. - * d) Replace 0x80000000 with MaxInt if source lane contains a +ve value. + * Following routine handles special floating point values(NaN/Inf/-Inf/Max/Min) for casting operation. + * If src is NaN, the result is 0. + * If the src is negative infinity or any value less than or equal to the value of Integer.MIN_VALUE, + * the result is equal to the value of Integer.MIN_VALUE. + * If the src is positive infinity or any value greater than or equal to the value of Integer.MAX_VALUE, + * the result is equal to the value of Integer.MAX_VALUE. */ - -void C2_MacroAssembler::vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, - KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, - Register scratch, int vec_enc) { +void C2_MacroAssembler::vector_cast_float_special_cases_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, + Register scratch, AddressLiteral float_sign_flip, + int vec_enc) { Label done; - evcvttpd2qq(dst, src, vec_enc); - evmovdqul(xtmp1, k0, double_sign_flip, false, vec_enc, scratch); - evpcmpeqq(ktmp1, xtmp1, dst, vec_enc); - kortestwl(ktmp1, ktmp1); - jccb(Assembler::equal, done); - - vpxor(xtmp2, xtmp2, xtmp2, vec_enc); - evcmppd(ktmp2, k0, src, src, Assembler::UNORD_Q, vec_enc); - evmovdquq(dst, ktmp2, xtmp2, true, vec_enc); - - kxorwl(ktmp1, ktmp1, ktmp2); - evcmppd(ktmp1, ktmp1, src, xtmp2, Assembler::NLT_UQ, vec_enc); - vpternlogq(xtmp2, 0x11, xtmp1, xtmp1, vec_enc); - evmovdquq(dst, ktmp1, xtmp2, true, vec_enc); - bind(done); -} - -void C2_MacroAssembler::vector_castF2I_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, - XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, - AddressLiteral float_sign_flip, Register scratch, int vec_enc) { - Label done; - vcvttps2dq(dst, src, vec_enc); vmovdqu(xtmp1, float_sign_flip, scratch, vec_enc); vpcmpeqd(xtmp2, dst, xtmp1, vec_enc); vptest(xtmp2, xtmp2, vec_enc); @@ -4073,11 +4097,11 @@ void C2_MacroAssembler::vector_castF2I_avx(XMMRegister dst, XMMRegister src, XMM bind(done); } -void C2_MacroAssembler::vector_castF2I_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, - KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, - Register scratch, int vec_enc) { +void C2_MacroAssembler::vector_cast_float_special_cases_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2, + Register scratch, AddressLiteral float_sign_flip, + int vec_enc) { Label done; - vcvttps2dq(dst, src, vec_enc); evmovdqul(xtmp1, k0, float_sign_flip, false, vec_enc, scratch); Assembler::evpcmpeqd(ktmp1, k0, xtmp1, dst, vec_enc); kortestwl(ktmp1, ktmp1); @@ -4094,6 +4118,115 @@ void C2_MacroAssembler::vector_castF2I_evex(XMMRegister dst, XMMRegister src, XM bind(done); } +/* + * Following routine handles special floating point values(NaN/Inf/-Inf/Max/Min) for casting operation. + * If src is NaN, the result is 0. + * If the src is negative infinity or any value less than or equal to the value of Long.MIN_VALUE, + * the result is equal to the value of Long.MIN_VALUE. + * If the src is positive infinity or any value greater than or equal to the value of Long.MAX_VALUE, + * the result is equal to the value of Long.MAX_VALUE. + */ +void C2_MacroAssembler::vector_cast_double_special_cases_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2, + Register scratch, AddressLiteral double_sign_flip, + int vec_enc) { + Label done; + evmovdqul(xtmp1, k0, double_sign_flip, false, vec_enc, scratch); + evpcmpeqq(ktmp1, xtmp1, dst, vec_enc); + kortestwl(ktmp1, ktmp1); + jccb(Assembler::equal, done); + + vpxor(xtmp2, xtmp2, xtmp2, vec_enc); + evcmppd(ktmp2, k0, src, src, Assembler::UNORD_Q, vec_enc); + evmovdquq(dst, ktmp2, xtmp2, true, vec_enc); + + kxorwl(ktmp1, ktmp1, ktmp2); + evcmppd(ktmp1, ktmp1, src, xtmp2, Assembler::NLT_UQ, vec_enc); + vpternlogq(xtmp2, 0x11, xtmp1, xtmp1, vec_enc); + evmovdquq(dst, ktmp1, xtmp2, true, vec_enc); + bind(done); +} + +/* + * Algorithm for vector D2L and F2I conversions:- + * a) Perform vector D2L/F2I cast. + * b) Choose fast path if none of the result vector lane contains 0x80000000 value. + * It signifies that source value could be any of the special floating point + * values(NaN,-Inf,Inf,Max,-Min). + * c) Set destination to zero if source is NaN value. + * d) Replace 0x80000000 with MaxInt if source lane contains a +ve value. + */ + +void C2_MacroAssembler::vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + Register scratch, int vec_enc) { + evcvttpd2qq(dst, src, vec_enc); + vector_cast_double_special_cases_evex(dst, src, xtmp1, xtmp2, ktmp1, ktmp2, scratch, double_sign_flip, vec_enc); +} + +void C2_MacroAssembler::vector_castF2I_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, + AddressLiteral float_sign_flip, Register scratch, int vec_enc) { + vcvttps2dq(dst, src, vec_enc); + vector_cast_float_special_cases_avx(dst, src, xtmp1, xtmp2, xtmp3, xtmp4, scratch, float_sign_flip, vec_enc); +} + +void C2_MacroAssembler::vector_castF2I_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, + Register scratch, int vec_enc) { + vcvttps2dq(dst, src, vec_enc); + vector_cast_float_special_cases_evex(dst, src, xtmp1, xtmp2, ktmp1, ktmp2, scratch, float_sign_flip, vec_enc); +} + +#ifdef _LP64 +void C2_MacroAssembler::vector_round_double_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc) { + // Perform floor(val+0.5) operation under the influence of MXCSR.RC mode roundTowards -inf. + // and re-instantiate original MXCSR.RC mode after that. + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); + ldmxcsr(new_mxcsr, scratch); + mov64(scratch, julong_cast(0.5L)); + evpbroadcastq(xtmp1, scratch, vec_enc); + vaddpd(xtmp1, src , xtmp1, vec_enc); + evcvtpd2qq(dst, xtmp1, vec_enc); + vector_cast_double_special_cases_evex(dst, src, xtmp1, xtmp2, ktmp1, ktmp2, scratch, double_sign_flip, vec_enc); + ldmxcsr(mxcsr_std, scratch); +} + +void C2_MacroAssembler::vector_round_float_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc) { + // Perform floor(val+0.5) operation under the influence of MXCSR.RC mode roundTowards -inf. + // and re-instantiate original MXCSR.RC mode after that. + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); + ldmxcsr(new_mxcsr, scratch); + movl(scratch, jint_cast(0.5)); + movq(xtmp1, scratch); + vbroadcastss(xtmp1, xtmp1, vec_enc); + vaddps(xtmp1, src , xtmp1, vec_enc); + vcvtps2dq(dst, xtmp1, vec_enc); + vector_cast_float_special_cases_evex(dst, src, xtmp1, xtmp2, ktmp1, ktmp2, scratch, float_sign_flip, vec_enc); + ldmxcsr(mxcsr_std, scratch); +} + +void C2_MacroAssembler::vector_round_float_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + XMMRegister xtmp3, XMMRegister xtmp4, AddressLiteral float_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc) { + // Perform floor(val+0.5) operation under the influence of MXCSR.RC mode roundTowards -inf. + // and re-instantiate original MXCSR.RC mode after that. + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); + ldmxcsr(new_mxcsr, scratch); + movl(scratch, jint_cast(0.5)); + movq(xtmp1, scratch); + vbroadcastss(xtmp1, xtmp1, vec_enc); + vaddps(xtmp1, src , xtmp1, vec_enc); + vcvtps2dq(dst, xtmp1, vec_enc); + vector_cast_float_special_cases_avx(dst, src, xtmp1, xtmp2, xtmp3, xtmp4, scratch, float_sign_flip, vec_enc); + ldmxcsr(mxcsr_std, scratch); +} +#endif + void C2_MacroAssembler::vector_unsigned_cast(XMMRegister dst, XMMRegister src, int vlen_enc, BasicType from_elem_bt, BasicType to_elem_bt) { switch (from_elem_bt) { @@ -4321,6 +4454,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..5f8e38a93b2395921f2ed094bdd248af7cb6245c 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, @@ -304,6 +303,7 @@ public: KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, Register scratch, int vec_enc); + void vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, Register scratch, int vec_enc); @@ -311,10 +311,45 @@ public: void vector_unsigned_cast(XMMRegister dst, XMMRegister src, int vlen_enc, BasicType from_elem_bt, BasicType to_elem_bt); + void vector_cast_double_special_cases_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, Register scratch, AddressLiteral double_sign_flip, + int vec_enc); + + void vector_cast_float_special_cases_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, Register scratch, AddressLiteral float_sign_flip, + int vec_enc); + + void vector_cast_float_special_cases_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, + Register scratch, AddressLiteral float_sign_flip, + int vec_enc); + +#ifdef _LP64 + void vector_round_double_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc); + + void vector_round_float_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc); + + void vector_round_float_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + XMMRegister xtmp3, XMMRegister xtmp4, AddressLiteral float_sign_flip, + AddressLiteral new_mxcsr, Register scratch, int vec_enc); +#endif + void evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, BasicType bt, int vlen_enc); 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/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 8c74db952e8a7e611f86a0de89615449dd96d5ce..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"); } 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..855c855089d2f9531e14b5313111bcb6e52a7aa6 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -332,21 +332,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()); } @@ -2267,12 +2252,12 @@ void MacroAssembler::fld_x(AddressLiteral src) { Assembler::fld_x(as_Address(src)); } -void MacroAssembler::ldmxcsr(AddressLiteral src) { +void MacroAssembler::ldmxcsr(AddressLiteral src, Register scratchReg) { if (reachable(src)) { Assembler::ldmxcsr(as_Address(src)); } else { - lea(rscratch1, src); - Assembler::ldmxcsr(Address(rscratch1, 0)); + lea(scratchReg, src); + Assembler::ldmxcsr(Address(scratchReg, 0)); } } @@ -3593,6 +3578,191 @@ 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() { + int num_xmm_registers = XMMRegisterImpl::available_xmm_registers(); +#if defined(WINDOWS) && defined(_LP64) + XMMRegSet result = XMMRegSet::range(xmm0, xmm5); + if (num_xmm_registers > 16) { + result += XMMRegSet::range(xmm16, as_XMMRegister(num_xmm_registers - 1)); + } + return result; +#else + return XMMRegSet::range(xmm0, as_XMMRegister(num_xmm_registers - 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 @@ -8950,6 +9120,80 @@ void MacroAssembler::convert_f2l(Register dst, XMMRegister src) { bind(done); } +void MacroAssembler::round_float(Register dst, XMMRegister src, Register rtmp, Register rcx) { + // Following code is line by line assembly translation rounding algorithm. + // Please refer to java.lang.Math.round(float) algorithm for details. + const int32_t FloatConsts_EXP_BIT_MASK = 0x7F800000; + const int32_t FloatConsts_SIGNIFICAND_WIDTH = 24; + const int32_t FloatConsts_EXP_BIAS = 127; + const int32_t FloatConsts_SIGNIF_BIT_MASK = 0x007FFFFF; + const int32_t MINUS_32 = 0xFFFFFFE0; + Label L_special_case, L_block1, L_exit; + movl(rtmp, FloatConsts_EXP_BIT_MASK); + movdl(dst, src); + andl(dst, rtmp); + sarl(dst, FloatConsts_SIGNIFICAND_WIDTH - 1); + movl(rtmp, FloatConsts_SIGNIFICAND_WIDTH - 2 + FloatConsts_EXP_BIAS); + subl(rtmp, dst); + movl(rcx, rtmp); + movl(dst, MINUS_32); + testl(rtmp, dst); + jccb(Assembler::notEqual, L_special_case); + movdl(dst, src); + andl(dst, FloatConsts_SIGNIF_BIT_MASK); + orl(dst, FloatConsts_SIGNIF_BIT_MASK + 1); + movdl(rtmp, src); + testl(rtmp, rtmp); + jccb(Assembler::greaterEqual, L_block1); + negl(dst); + bind(L_block1); + sarl(dst); + addl(dst, 0x1); + sarl(dst, 0x1); + jmp(L_exit); + bind(L_special_case); + convert_f2i(dst, src); + bind(L_exit); +} + +void MacroAssembler::round_double(Register dst, XMMRegister src, Register rtmp, Register rcx) { + // Following code is line by line assembly translation rounding algorithm. + // Please refer to java.lang.Math.round(double) algorithm for details. + const int64_t DoubleConsts_EXP_BIT_MASK = 0x7FF0000000000000L; + const int64_t DoubleConsts_SIGNIFICAND_WIDTH = 53; + const int64_t DoubleConsts_EXP_BIAS = 1023; + const int64_t DoubleConsts_SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL; + const int64_t MINUS_64 = 0xFFFFFFFFFFFFFFC0L; + Label L_special_case, L_block1, L_exit; + mov64(rtmp, DoubleConsts_EXP_BIT_MASK); + movq(dst, src); + andq(dst, rtmp); + sarq(dst, DoubleConsts_SIGNIFICAND_WIDTH - 1); + mov64(rtmp, DoubleConsts_SIGNIFICAND_WIDTH - 2 + DoubleConsts_EXP_BIAS); + subq(rtmp, dst); + movq(rcx, rtmp); + mov64(dst, MINUS_64); + testq(rtmp, dst); + jccb(Assembler::notEqual, L_special_case); + movq(dst, src); + mov64(rtmp, DoubleConsts_SIGNIF_BIT_MASK); + andq(dst, rtmp); + mov64(rtmp, DoubleConsts_SIGNIF_BIT_MASK + 1); + orq(dst, rtmp); + movq(rtmp, src); + testq(rtmp, rtmp); + jccb(Assembler::greaterEqual, L_block1); + negq(dst); + bind(L_block1); + sarq(dst); + addq(dst, 0x1); + sarq(dst, 0x1); + jmp(L_exit); + bind(L_special_case); + convert_d2l(dst, src); + bind(L_exit); +} + void MacroAssembler::convert_d2l(Register dst, XMMRegister src) { Label done; cvttsd2siq(dst, src); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 3593874866ca81157b1fa49f975034d866383443..303b6b0c83c1e8e2a8e9cd698ef7431909cea51d 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( @@ -880,7 +906,7 @@ class MacroAssembler: public Assembler { void fld_x(AddressLiteral src); void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } - void ldmxcsr(AddressLiteral src); + void ldmxcsr(AddressLiteral src, Register scratchReg = rscratch1); #ifdef _LP64 private: @@ -1968,6 +1994,8 @@ public: void convert_d2i(Register dst, XMMRegister src); void convert_f2l(Register dst, XMMRegister src); void convert_d2l(Register dst, XMMRegister src); + void round_double(Register dst, XMMRegister src, Register rtmp, Register rcx); + void round_float(Register dst, XMMRegister src, Register rtmp, Register rcx); void cache_wb(Address line); void cache_wbsync(bool is_pre); 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_x86.cpp b/src/hotspot/cpu/x86/register_x86.cpp index 2a07a9eb19c3b670cb8e86f59aa8e3cdd83fea8f..d86cb1f0820842e31dda08707520efb6bc79eab2 100644 --- a/src/hotspot/cpu/x86/register_x86.cpp +++ b/src/hotspot/cpu/x86/register_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" + #include "register_x86.hpp" #ifndef AMD64 diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index b9ac28902407560b1d03df290b731b4f407ede7c..7bb0be2094395114d921d608c58b4cfab170069d 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,9 @@ #define CPU_X86_REGISTER_X86_HPP #include "asm/register.hpp" +#include "runtime/globals.hpp" +#include "utilities/count_leading_zeros.hpp" +#include "utilities/powerOfTwo.hpp" class VMRegImpl; typedef VMRegImpl* VMReg; @@ -135,7 +138,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 { @@ -161,6 +164,18 @@ class XMMRegisterImpl: public AbstractRegisterImpl { bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } const char* name() const; const char* sub_word_name(int offset) const; + + // Actually available XMM registers for use, depending on actual CPU capabilities + // and flags. + static int available_xmm_registers() { + int num_xmm_regs = XMMRegisterImpl::number_of_registers; +#ifdef _LP64 + if (UseAVX < 3) { + num_xmm_regs /= 2; + } +#endif + return num_xmm_regs; + } }; @@ -201,11 +216,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 +224,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 +287,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 8bfbe3303da9e9a8f1dc0604cdbaaf6329d780c5..75ddae6319974969858e1a76e7e9b21ac2791495 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -174,10 +174,7 @@ PRAGMA_DIAG_PUSH PRAGMA_NONNULL_IGNORED OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { int off = 0; - int num_xmm_regs = XMMRegisterImpl::number_of_registers; - if (UseAVX < 3) { - num_xmm_regs = num_xmm_regs/2; - } + int num_xmm_regs = XMMRegisterImpl::available_xmm_registers(); #if COMPILER2_OR_JVMCI if (save_vectors && UseAVX == 0) { save_vectors = false; // vectors larger than 16 byte long are supported only with AVX @@ -367,10 +364,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ PRAGMA_DIAG_POP void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) { - int num_xmm_regs = XMMRegisterImpl::number_of_registers; - if (UseAVX < 3) { - num_xmm_regs = num_xmm_regs/2; - } + int num_xmm_regs = XMMRegisterImpl::available_xmm_registers(); if (frame::arg_reg_save_area_bytes != 0) { // Pop arg register save area __ addptr(rsp, frame::arg_reg_save_area_bytes); 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/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/vmreg_x86.hpp b/src/hotspot/cpu/x86/vmreg_x86.hpp index 58df28f8491b96a3df528aa14f9f4ff8b5574ef9..a2d44a2cebed2f4844a0ff0fee0988b475aa8eb7 100644 --- a/src/hotspot/cpu/x86/vmreg_x86.hpp +++ b/src/hotspot/cpu/x86/vmreg_x86.hpp @@ -25,7 +25,7 @@ #ifndef CPU_X86_VMREG_X86_HPP #define CPU_X86_VMREG_X86_HPP - +#include "register_x86.hpp" inline bool is_Register() { return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; @@ -36,14 +36,8 @@ inline bool is_FloatRegister() { } inline bool is_XMMRegister() { - int uarch_max_xmm = ConcreteRegisterImpl::max_xmm; - -#ifdef _LP64 - if (UseAVX < 3) { - int half_xmm = (XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers) / 2; - uarch_max_xmm -= half_xmm; - } -#endif + int uarch_max_xmm = ConcreteRegisterImpl::max_fpr + + (XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::available_xmm_registers()); return (value() >= ConcreteRegisterImpl::max_fpr && value() < uarch_max_xmm); } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 7ff67e9a085562722946e6c04f95cb18e4136fb6..cf182d9880d382a147b1276cef7b3457512e2d68 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; @@ -1464,6 +1468,16 @@ const bool Matcher::match_rule_supported(int opcode) { return false; } break; + case Op_RoundVF: + if (UseAVX < 2) { // enabled for AVX2 only + return false; + } + break; + case Op_RoundVD: + if (UseAVX < 3) { + return false; // enabled for AVX3 only + } + break; case Op_CompareAndSwapL: #ifdef _LP64 case Op_CompareAndSwapP: @@ -1568,6 +1582,12 @@ const bool Matcher::match_rule_supported(int opcode) { return false; } break; + case Op_RoundF: + case Op_RoundD: + if (!is_LP64) { + return false; + } + break; case Op_CopySignD: case Op_CopySignF: if (UseAVX < 3 || !is_LP64) { @@ -1813,6 +1833,11 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; + case Op_RoundVD: + if (!VM_Version::supports_avx512dq()) { + return false; + } + break; case Op_VectorCastF2X: if (is_subword_type(bt) || bt == T_LONG) { return false; @@ -1861,6 +1886,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. } @@ -7157,13 +7194,14 @@ instruct vcastFtoD_reg(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} -instruct vcastFtoI_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rRegP scratch, rFlagsReg cr) %{ + +instruct castFtoI_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rRegP scratch, rFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n) < 64 && Matcher::vector_element_basic_type(n) == T_INT); match(Set dst (VectorCastF2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP xtmp4, TEMP scratch, KILL cr); - format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $xtmp3 and $xtmp4 as TEMP" %} + format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $xtmp3, $xtmp4 and $scratch as TEMP" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); __ vector_castF2I_avx($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, @@ -7173,13 +7211,13 @@ instruct vcastFtoI_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, ve ins_pipe( pipe_slow ); %} -instruct vcastFtoI_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ +instruct castFtoI_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ predicate((VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n) == 64) && Matcher::vector_element_basic_type(n) == T_INT); match(Set dst (VectorCastF2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); - format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1 and $ktmp2 as TEMP" %} + format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1, $ktmp2 and $scratch as TEMP" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); __ vector_castF2I_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, @@ -7200,11 +7238,11 @@ instruct vcastDtoF_reg(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} -instruct vcastDtoL_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ +instruct castDtoL_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ predicate(Matcher::vector_element_basic_type(n) == T_LONG); match(Set dst (VectorCastD2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); - format %{ "vector_cast_d2l $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1 and $ktmp2 as TEMP" %} + format %{ "vector_cast_d2l $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1, $ktmp2 and $scratch as TEMP" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); __ vector_castD2L_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, @@ -7230,6 +7268,56 @@ instruct vucast(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} +#ifdef _LP64 +instruct vround_float_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rRegP scratch, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx512vl() && + Matcher::vector_length_in_bytes(n) < 64 && + Matcher::vector_element_basic_type(n) == T_INT); + match(Set dst (RoundVF src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP xtmp4, TEMP scratch, KILL cr); + format %{ "vector_round_float $dst,$src\t! using $xtmp1, $xtmp2, $xtmp3, $xtmp4 and $scratch as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + InternalAddress new_mxcsr = $constantaddress((jint)0x3F80); + __ vector_round_float_avx($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $xtmp4$$XMMRegister, + ExternalAddress(vector_float_signflip()), new_mxcsr, $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround_float_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ + predicate((VM_Version::supports_avx512vl() || + Matcher::vector_length_in_bytes(n) == 64) && + Matcher::vector_element_basic_type(n) == T_INT); + match(Set dst (RoundVF src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); + format %{ "vector_round_float $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1, $ktmp2 and $scratch as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + InternalAddress new_mxcsr = $constantaddress((jint)0x3F80); + __ vector_round_float_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister, + ExternalAddress(vector_float_signflip()), new_mxcsr, $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ + predicate(Matcher::vector_element_basic_type(n) == T_LONG); + match(Set dst (RoundVD src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); + format %{ "vector_round_long $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1, $ktmp2 and $scratch as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + InternalAddress new_mxcsr = $constantaddress((jint)0x3F80); + __ vector_round_double_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister, + ExternalAddress(vector_double_signflip()), new_mxcsr, $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} +#endif // --------------------------------- VectorMaskCmp -------------------------------------- instruct vcmpFD(legVec dst, legVec src1, legVec src2, immI8 cond) %{ @@ -8571,28 +8659,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 3bb01e3eeaeb81f7bc9d27df43a9923601c3fe7d..9bba150516ed134ae16e34b52cf97242f2ef22e7 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -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..62132ea930f867ab04f8d9010e7d1dfbd0e60dfd 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 %{ - __ leal($dst$$Register, Address($src0$$Register, $src1$$constant)); + 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($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)); @@ -10703,6 +10821,28 @@ instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr) ins_pipe(pipe_slow); %} +instruct round_double_reg(rRegL dst, regD src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr) +%{ + match(Set dst (RoundD src)); + effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr); + format %{ "round_double $dst,$src \t! using $rtmp and $rcx as TEMP"%} + ins_encode %{ + __ round_double($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register); + %} + ins_pipe(pipe_slow); +%} + +instruct round_float_reg(rRegI dst, regF src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr) +%{ + match(Set dst (RoundF src)); + effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr); + format %{ "round_float $dst,$src" %} + ins_encode %{ + __ round_float($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register); + %} + ins_pipe(pipe_slow); +%} + instruct convI2F_reg_reg(regF dst, rRegI src) %{ predicate(!UseXmmI2F); @@ -11685,34 +11825,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/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/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 18b908cfc8fc0eec9e0369b342807920521158de..cba539caf425355a5d9357141b3dc7d3fdce114a 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) { @@ -2463,6 +2496,8 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) { strncpy(cpuinfo, "IA64", length); #elif defined(PPC) strncpy(cpuinfo, "PPC64", length); +#elif defined(RISCV) + strncpy(cpuinfo, "RISCV64", length); #elif defined(S390) strncpy(cpuinfo, "S390", length); #elif defined(SPARC) @@ -3939,23 +3974,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 +4003,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/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 6e94b47712f95f9194a3d4a3a138eec629b9535e..6ec5bbd6c2cd9af117de8fef5b864880218c273e 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1244,8 +1244,10 @@ void set_signal_handler(int sig, bool do_check = true) { } #endif - // Save handler setup for later checking - vm_handlers.set(sig, &sigAct); + // Save handler setup for possible later checking + if (do_check) { + vm_handlers.set(sig, &sigAct); + } do_check_signal_periodically[sig] = do_check; int ret = sigaction(sig, &sigAct, &oldAct); diff --git a/src/hotspot/os/windows/attachListener_windows.cpp b/src/hotspot/os/windows/attachListener_windows.cpp index 710afc410051f627ff45807be7454e948e263a8b..07a214d4352ca693598183e3ed9e762aa55d6654 100644 --- a/src/hotspot/os/windows/attachListener_windows.cpp +++ b/src/hotspot/os/windows/attachListener_windows.cpp @@ -154,7 +154,7 @@ class Win32AttachOperation: public AttachOperation { } public: - void Win32AttachOperation::complete(jint result, bufferedStream* result_stream); + void complete(jint result, bufferedStream* result_stream); }; diff --git a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp index 37221953a7777e889490ded0daf3d8202e79c542..75ca68e43fb4891e99cb6ca939521a57647a161d 100644 --- a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp @@ -41,4 +41,4 @@ class ICache : public AbstractICache { } }; -#endif // OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP \ No newline at end of file +#endif // OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2610af6cdd0f50db6d50a7de3c7bd8569c5499d --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// nothing required here diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..761da5d743edd921d92dff9c3a6d059ddad7eb9e --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP + +#include "runtime/vm_version.hpp" + +// Implementation of class atomic + +// Note that memory_order_conservative requires a full barrier after atomic stores. +// See https://patchwork.kernel.org/patch/3575821/ + +template +struct Atomic::PlatformAdd { + template + D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; + } + + template + D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { + return add_and_fetch(dest, add_value, order) - add_value; + } +}; + +template +template +inline T Atomic::PlatformXchg::operator()(T volatile* dest, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(byte_size == sizeof(T)); + T res = __atomic_exchange_n(dest, exchange_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; +} + +// __attribute__((unused)) on dest is to get rid of spurious GCC warnings. +template +template +inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attribute__((unused)), + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(byte_size == sizeof(T)); + T value = compare_value; + if (order != memory_order_relaxed) { + FULL_MEM_BARRIER; + } + + __atomic_compare_exchange(dest, &value, &exchange_value, /* weak */ false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + + if (order != memory_order_relaxed) { + FULL_MEM_BARRIER; + } + return value; +} + +template<> +template +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)), + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + if (order != memory_order_relaxed) { + FULL_MEM_BARRIER; + } + T rv; + int tmp; + __asm volatile( + "1:\n\t" + " addiw %[tmp], %[cv], 0\n\t" // make sure compare_value signed_extend + " lr.w.aq %[rv], (%[dest])\n\t" + " bne %[rv], %[tmp], 2f\n\t" + " sc.w.rl %[tmp], %[ev], (%[dest])\n\t" + " bnez %[tmp], 1b\n\t" + "2:\n\t" + : [rv] "=&r" (rv), [tmp] "=&r" (tmp) + : [ev] "r" (exchange_value), [dest] "r" (dest), [cv] "r" (compare_value) + : "memory"); + if (order != memory_order_relaxed) { + FULL_MEM_BARRIER; + } + return rv; +} + +template +struct Atomic::PlatformOrderedLoad +{ + template + T operator()(const volatile T* p) const { T data; __atomic_load(const_cast(p), &data, __ATOMIC_ACQUIRE); return data; } +}; + +template +struct Atomic::PlatformOrderedStore +{ + template + void operator()(volatile T* p, T v) const { __atomic_store(const_cast(p), &v, __ATOMIC_RELEASE); } +}; + +template +struct Atomic::PlatformOrderedStore +{ + template + void operator()(volatile T* p, T v) const { release_store(p, v); OrderAccess::fence(); } +}; + +#endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP diff --git a/src/hotspot/share/gc/shared/cardGeneration.inline.hpp b/src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp similarity index 56% rename from src/hotspot/share/gc/shared/cardGeneration.inline.hpp rename to src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp index bd8285af679de0b6640abee295b683562e2d079d..28868c7640640384799472f90cb0dea0647a9f12 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.inline.hpp +++ b/src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,35 +23,23 @@ * */ -#ifndef SHARE_GC_SHARED_CARDGENERATION_INLINE_HPP -#define SHARE_GC_SHARED_CARDGENERATION_INLINE_HPP +#ifndef OS_CPU_LINUX_RISCV_BYTES_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_BYTES_LINUX_RISCV_HPP -#include "gc/shared/cardGeneration.hpp" +#include -#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(); +// Efficient swapping of data bytes from Java byte +// ordering to native byte ordering and vice versa. +inline u2 Bytes::swap_u2(u2 x) { + return bswap_16(x); } -inline bool CardGeneration::is_in(const void* p) const { - return space()->is_in(p); +inline u4 Bytes::swap_u4(u4 x) { + return bswap_32(x); } -inline CompactibleSpace* CardGeneration::first_compaction_space() const { - return space(); +inline u8 Bytes::swap_u8(u8 x) { + return bswap_64(x); } -#endif // SHARE_GC_SHARED_CARDGENERATION_INLINE_HPP +#endif // OS_CPU_LINUX_RISCV_BYTES_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..147cfdf3c100d541d42f9ce554b6ba57157929b7 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP + +// Empty for build system + +#endif // OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1aa58f27871d2e3a1d6dae17ca0a6173a20e3a89 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP + +#include + +// +// Support for building on older Linux systems +// + +#ifndef SYS_memfd_create +#define SYS_memfd_create 279 +#endif +#ifndef SYS_fallocate +#define SYS_fallocate 47 +#endif + +#endif // OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..297414bfcd510b9354184fb6d6f4c6c0b571c05b --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_RISCV_VM_GLOBALS_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_VM_GLOBALS_LINUX_RISCV_HPP + +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + +define_pd_global(bool, DontYieldALot, false); +define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 2048); + +define_pd_global(intx, CompilerThreadStackSize, 2048); + +define_pd_global(uintx, JVMInvokeMethodSlack, 8192); + +// Used on 64 bit platforms for UseCompressedOops base address +define_pd_global(uintx, HeapBaseMinAddress, 2 * G); + +#endif // OS_CPU_LINUX_RISCV_VM_GLOBALS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1c33dc1e87fadcde29dc54ad29c38cf005441e6b --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP + +// Included in orderAccess.hpp header file. + +#include "runtime/vm_version.hpp" + +// Implementation of class OrderAccess. + +inline void OrderAccess::loadload() { acquire(); } +inline void OrderAccess::storestore() { release(); } +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + +#define FULL_MEM_BARRIER __sync_synchronize() +#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE); +#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE); + +inline void OrderAccess::acquire() { + READ_MEM_BARRIER; +} + +inline void OrderAccess::release() { + WRITE_MEM_BARRIER; +} + +inline void OrderAccess::fence() { + FULL_MEM_BARRIER; +} + +inline void OrderAccess::cross_modify_fence_impl() { + asm volatile("fence.i" : : : "memory"); + if (UseConservativeFence) { + asm volatile("fence ir, ir" : : : "memory"); + } +} + +#endif // OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f46bbab0a2e1241668e0892131c29e959cab679 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp @@ -0,0 +1,466 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// no precompiled headers +#include "asm/macroAssembler.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/codeCache.hpp" +#include "code/icBuffer.hpp" +#include "code/nativeInst.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm.h" +#include "memory/allocation.inline.hpp" +#include "os_share_linux.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/osThread.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/timer.hpp" +#include "signals_posix.hpp" +#include "utilities/debug.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" + +// put OS-includes here +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +#define REG_LR 1 +#define REG_FP 8 + +NOINLINE address os::current_stack_pointer() { + return (address)__builtin_frame_address(0); +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + return (char*) -1; +} + +address os::Posix::ucontext_get_pc(const ucontext_t * uc) { + return (address)uc->uc_mcontext.__gregs[REG_PC]; +} + +void os::Posix::ucontext_set_pc(ucontext_t * uc, address pc) { + uc->uc_mcontext.__gregs[REG_PC] = (intptr_t)pc; +} + +intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) { + return (intptr_t*)uc->uc_mcontext.__gregs[REG_SP]; +} + +intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) { + return (intptr_t*)uc->uc_mcontext.__gregs[REG_FP]; +} + +address os::fetch_frame_from_context(const void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { + address epc; + const ucontext_t* uc = (const ucontext_t*)ucVoid; + + if (uc != NULL) { + epc = os::Posix::ucontext_get_pc(uc); + if (ret_sp != NULL) { + *ret_sp = os::Linux::ucontext_get_sp(uc); + } + if (ret_fp != NULL) { + *ret_fp = os::Linux::ucontext_get_fp(uc); + } + } else { + epc = NULL; + if (ret_sp != NULL) { + *ret_sp = (intptr_t *)NULL; + } + if (ret_fp != NULL) { + *ret_fp = (intptr_t *)NULL; + } + } + + return epc; +} + +frame os::fetch_compiled_frame_from_context(const void* ucVoid) { + const ucontext_t* uc = (const ucontext_t*)ucVoid; + // In compiled code, the stack banging is performed before RA + // has been saved in the frame. RA is live, and SP and FP + // belong to the caller. + intptr_t* frame_fp = os::Linux::ucontext_get_fp(uc); + intptr_t* frame_sp = os::Linux::ucontext_get_sp(uc); + address frame_pc = (address)(uc->uc_mcontext.__gregs[REG_LR] + - NativeInstruction::instruction_size); + return frame(frame_sp, frame_fp, frame_pc); +} + +frame os::fetch_frame_from_context(const void* ucVoid) { + intptr_t* frame_sp = NULL; + intptr_t* frame_fp = NULL; + address epc = fetch_frame_from_context(ucVoid, &frame_sp, &frame_fp); + return frame(frame_sp, frame_fp, epc); +} + +// By default, gcc always saves frame pointer rfp on this stack. This +// may get turned off by -fomit-frame-pointer. +frame os::get_sender_for_C_frame(frame* fr) { + return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); +} + +NOINLINE frame os::current_frame() { + intptr_t **sender_sp = (intptr_t **)__builtin_frame_address(0); + if (sender_sp != NULL) { + frame myframe((intptr_t*)os::current_stack_pointer(), + sender_sp[frame::link_offset], + CAST_FROM_FN_PTR(address, os::current_frame)); + if (os::is_first_C_frame(&myframe)) { + // stack is not walkable + return frame(); + } else { + return os::get_sender_for_C_frame(&myframe); + } + } else { + ShouldNotReachHere(); + return frame(); + } +} + +// Utility functions +bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, + ucontext_t* uc, JavaThread* thread) { + + // decide if this trap can be handled by a stub + address stub = NULL; + + address pc = NULL; + + //%note os_trap_1 + if (info != NULL && uc != NULL && thread != NULL) { + pc = (address) os::Posix::ucontext_get_pc(uc); + + address addr = (address) info->si_addr; + + // Make sure the high order byte is sign extended, as it may be masked away by the hardware. + if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) { + addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56)); + } + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV) { + // check if fault address is within thread stack + if (thread->is_in_full_stack(addr)) { + if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) { + return true; // continue + } + } + } + + if (thread->thread_state() == _thread_in_Java) { + // Java thread running in Java code => find exception handler if any + // a fault inside compiled code, the interpreter, or a stub + + // Handle signal from NativeJump::patch_verified_entry(). + if ((sig == SIGILL || sig == SIGTRAP) + && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) { + if (TraceTraps) { + tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + } + stub = SharedRuntime::get_handle_wrong_method_stub(); + } else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { + stub = SharedRuntime::get_poll_stub(pc); + } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { + // BugId 4454115: A read from a MappedByteBuffer can fault + // here if the underlying file has been truncated. + // Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; + bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc)); + if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) { + address next_pc = pc + NativeCall::instruction_size; + if (is_unsafe_arraycopy) { + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); + } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } + } else if (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) { + // Pull a pointer to the error message out of the instruction + // stream. + const uint64_t *detail_msg_ptr + = (uint64_t*)(pc + NativeInstruction::instruction_size); + const char *detail_msg = (const char *)*detail_msg_ptr; + const char *msg = "stop"; + if (TraceTraps) { + tty->print_cr("trap: %s: (SIGILL)", msg); + } + + // End life with a fatal error, message and detail message and the context. + // Note: no need to do any post-processing here (e.g. signal chaining) + va_list va_dummy; + VMError::report_and_die(thread, uc, NULL, 0, msg, detail_msg, va_dummy); + va_end(va_dummy); + + ShouldNotReachHere(); + } else if (sig == SIGFPE && + (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { + stub = + SharedRuntime:: + continuation_for_implicit_exception(thread, + pc, + SharedRuntime:: + IMPLICIT_DIVIDE_BY_ZERO); + } else if (sig == SIGSEGV && + MacroAssembler::uses_implicit_null_check((void*)addr)) { + // Determination of interpreter/vtable stub/compiled code null exception + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } + } else if ((thread->thread_state() == _thread_in_vm || + thread->thread_state() == _thread_in_native) && + sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ + thread->doing_unsafe_access()) { + address next_pc = pc + NativeCall::instruction_size; + if (UnsafeCopyMemory::contains_pc(pc)) { + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); + } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } + + // jni_fast_GetField can trap at certain pc's if a GC kicks in + // and the heap gets shrunk before the field access. + if ((sig == SIGSEGV) || (sig == SIGBUS)) { + address addr_slow = JNI_FastGetField::find_slowcase_pc(pc); + if (addr_slow != (address)-1) { + stub = addr_slow; + } + } + } + + if (stub != NULL) { + // save all thread context in case we need to restore it + if (thread != NULL) { + thread->set_saved_exception_pc(pc); + } + + os::Posix::ucontext_set_pc(uc, stub); + return true; + } + + return false; // Mute compiler +} + +void os::Linux::init_thread_fpu_state(void) { +} + +int os::Linux::get_fpu_control_word(void) { + return 0; +} + +void os::Linux::set_fpu_control_word(int fpu_control) { +} + +//////////////////////////////////////////////////////////////////////////////// +// thread stack + +// Minimum usable stack sizes required to get to user code. Space for +// HotSpot guard pages is added later. +size_t os::Posix::_compiler_thread_min_stack_allowed = 72 * K; +size_t os::Posix::_java_thread_min_stack_allowed = 72 * K; +size_t os::Posix::_vm_internal_thread_min_stack_allowed = 72 * K; + +// return default stack size for thr_type +size_t os::Posix::default_stack_size(os::ThreadType thr_type) { + // default stack size (compiler thread needs larger stack) + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); + return s; +} + +///////////////////////////////////////////////////////////////////////////// +// helper functions for fatal error handler + +static const char* reg_abi_names[] = { + "pc", + "x1(ra)", "x2(sp)", "x3(gp)", "x4(tp)", + "x5(t0)", "x6(t1)", "x7(t2)", + "x8(s0)", "x9(s1)", + "x10(a0)", "x11(a1)", "x12(a2)", "x13(a3)", "x14(a4)", "x15(a5)", "x16(a6)", "x17(a7)", + "x18(s2)", "x19(s3)", "x20(s4)", "x21(s5)", "x22(s6)", "x23(s7)", "x24(s8)", "x25(s9)", "x26(s10)", "x27(s11)", + "x28(t3)", "x29(t4)","x30(t5)", "x31(t6)" +}; + +void os::print_context(outputStream *st, const void *context) { + if (context == NULL) { + return; + } + + const ucontext_t *uc = (const ucontext_t*)context; + st->print_cr("Registers:"); + for (int r = 0; r < 32; r++) { + st->print("%-*.*s=", 8, 8, reg_abi_names[r]); + print_location(st, uc->uc_mcontext.__gregs[r]); + } + st->cr(); + + intptr_t *frame_sp = (intptr_t *)os::Linux::ucontext_get_sp(uc); + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", p2i(frame_sp)); + print_hex_dump(st, (address)frame_sp, (address)(frame_sp + 64), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::Posix::ucontext_get_pc(uc); + print_instructions(st, pc, sizeof(char)); + st->cr(); +} + +void os::print_register_info(outputStream *st, const void *context) { + if (context == NULL) { + return; + } + + const ucontext_t *uc = (const ucontext_t*)context; + + st->print_cr("Register to memory mapping:"); + st->cr(); + + // this is horrendously verbose but the layout of the registers in the + // context does not match how we defined our abstract Register set, so + // we can't just iterate through the gregs area + + // this is only for the "general purpose" registers + + for (int r = 0; r < 32; r++) + st->print_cr("%-*.*s=" INTPTR_FORMAT, 8, 8, reg_abi_names[r], (uintptr_t)uc->uc_mcontext.__gregs[r]); + st->cr(); +} + +void os::setup_fpu() { +} + +#ifndef PRODUCT +void os::verify_stack_alignment() { + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); +} +#endif + +int os::extra_bang_size_in_bytes() { + return 0; +} + +extern "C" { + int SpinPause() { + return 0; + } + + void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { + if (from > to) { + const jshort *end = from + count; + while (from < end) { + *(to++) = *(from++); + } + } else if (from < to) { + const jshort *end = from; + from += count - 1; + to += count - 1; + while (from >= end) { + *(to--) = *(from--); + } + } + } + void _Copy_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { + if (from > to) { + const jint *end = from + count; + while (from < end) { + *(to++) = *(from++); + } + } else if (from < to) { + const jint *end = from; + from += count - 1; + to += count - 1; + while (from >= end) { + *(to--) = *(from--); + } + } + } + void _Copy_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { + if (from > to) { + const jlong *end = from + count; + while (from < end) { + os::atomic_copy64(from++, to++); + } + } else if (from < to) { + const jlong *end = from; + from += count - 1; + to += count - 1; + while (from >= end) { + os::atomic_copy64(from--, to--); + } + } + } + + void _Copy_arrayof_conjoint_bytes(const HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count); + } + void _Copy_arrayof_conjoint_jshorts(const HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 2); + } + void _Copy_arrayof_conjoint_jints(const HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 4); + } + void _Copy_arrayof_conjoint_jlongs(const HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 8); + } +}; diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6d4156306617d891df5e643495d03812c9eaaf96 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_VM_OS_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_VM_OS_LINUX_RISCV_HPP + + static void setup_fpu(); + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + + // Atomically copy 64 bits of data + static void atomic_copy64(const volatile void *src, volatile void *dst) { + *(jlong *) dst = *(const jlong *) src; + } + + // SYSCALL_RISCV_FLUSH_ICACHE is used to flush instruction cache. The "fence.i" instruction + // only work on the current hart, so kernel provides the icache flush syscall to flush icache + // on each hart. You can pass a flag to determine a global or local icache flush. + static void icache_flush(long int start, long int end) + { + const int SYSCALL_RISCV_FLUSH_ICACHE = 259; + register long int __a7 asm ("a7") = SYSCALL_RISCV_FLUSH_ICACHE; + register long int __a0 asm ("a0") = start; + register long int __a1 asm ("a1") = end; + // the flush can be applied to either all threads or only the current. + // 0 means a global icache flush, and the icache flush will be applied + // to other harts concurrently executing. + register long int __a2 asm ("a2") = 0; + __asm__ volatile ("ecall\n\t" + : "+r" (__a0) + : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a7) + : "memory"); + } + +#endif // OS_CPU_LINUX_RISCV_VM_OS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a6432c84ec71ff0ed92d0054c569fb6d71791aee --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_VM_PREFETCH_LINUX_RISCV_INLINE_HPP +#define OS_CPU_LINUX_RISCV_VM_PREFETCH_LINUX_RISCV_INLINE_HPP + +#include "runtime/prefetch.hpp" + + +inline void Prefetch::read (const void *loc, intx interval) { +} + +inline void Prefetch::write(void *loc, intx interval) { +} + +#endif // OS_CPU_LINUX_RISCV_VM_PREFETCH_LINUX_RISCV_INLINE_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3100572e9fdec5ef9eb6567f6956ba4a83f1e0f6 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/thread.inline.hpp" + +frame JavaThread::pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); +} + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, bool isInJava) { + + assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than ucontext info. + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); + return true; + } + + // At this point, we don't have a last_Java_frame, so + // we try to glean some information out of the ucontext + // if we were running Java code when SIGPROF came in. + if (isInJava) { + ucontext_t* uc = (ucontext_t*) ucontext; + + intptr_t* ret_fp = NULL; + intptr_t* ret_sp = NULL; + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); + if (addr == NULL || ret_sp == NULL ) { + // ucontext wasn't useful + return false; + } + + frame ret_frame(ret_sp, ret_fp, addr); + if (!ret_frame.safe_for_sender(this)) { +#ifdef COMPILER2 + frame ret_frame2(ret_sp, NULL, addr); + if (!ret_frame2.safe_for_sender(this)) { + // nothing else to try if the frame isn't good + return false; + } + ret_frame = ret_frame2; +#else + // nothing else to try if the frame isn't good + return false; +#endif /* COMPILER2 */ + } + *fr_addr = ret_frame; + return true; + } + + // nothing else to try + return false; +} + +void JavaThread::cache_global_variables() { } diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61e2cf85b63001b7075bae8622b6408b2d5f8a83 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_RISCV_THREAD_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_THREAD_LINUX_RISCV_HPP + + private: + void pd_initialize() { + _anchor.clear(); + } + + frame pd_last_frame(); + + public: + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset(); + } + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); + +#endif // OS_CPU_LINUX_RISCV_THREAD_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6cf7683a58602d4831d89b126c250338f4a82e2e --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP +#define OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_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) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ + nonstatic_field(OSThread, _pthread_id, pthread_t) + + +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ + \ + /**********************/ \ + /* Posix Thread IDs */ \ + /**********************/ \ + \ + declare_integer_type(OSThread::thread_id_t) \ + declare_unsigned_integer_type(pthread_t) + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a954dcf5768ce4cf8f70d51fdc5a2c56b3460754 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/register.hpp" +#include "runtime/os.hpp" +#include "runtime/os.inline.hpp" +#include "runtime/vm_version.hpp" + +#include +#include + +#ifndef HWCAP_ISA_I +#define HWCAP_ISA_I (1 << ('I' - 'A')) +#endif + +#ifndef HWCAP_ISA_M +#define HWCAP_ISA_M (1 << ('M' - 'A')) +#endif + +#ifndef HWCAP_ISA_A +#define HWCAP_ISA_A (1 << ('A' - 'A')) +#endif + +#ifndef HWCAP_ISA_F +#define HWCAP_ISA_F (1 << ('F' - 'A')) +#endif + +#ifndef HWCAP_ISA_D +#define HWCAP_ISA_D (1 << ('D' - 'A')) +#endif + +#ifndef HWCAP_ISA_C +#define HWCAP_ISA_C (1 << ('C' - 'A')) +#endif + +#ifndef HWCAP_ISA_V +#define HWCAP_ISA_V (1 << ('V' - 'A')) +#endif + +#define read_csr(csr) \ +({ \ + register unsigned long __v; \ + __asm__ __volatile__ ("csrr %0, %1" \ + : "=r" (__v) \ + : "i" (csr) \ + : "memory"); \ + __v; \ +}) + +uint32_t VM_Version::get_current_vector_length() { + assert(_features & CPU_V, "should not call this"); + return (uint32_t)read_csr(CSR_VLENB); +} + +void VM_Version::get_os_cpu_info() { + + uint64_t auxv = getauxval(AT_HWCAP); + + static_assert(CPU_I == HWCAP_ISA_I, "Flag CPU_I must follow Linux HWCAP"); + static_assert(CPU_M == HWCAP_ISA_M, "Flag CPU_M must follow Linux HWCAP"); + static_assert(CPU_A == HWCAP_ISA_A, "Flag CPU_A must follow Linux HWCAP"); + static_assert(CPU_F == HWCAP_ISA_F, "Flag CPU_F must follow Linux HWCAP"); + static_assert(CPU_D == HWCAP_ISA_D, "Flag CPU_D must follow Linux HWCAP"); + static_assert(CPU_C == HWCAP_ISA_C, "Flag CPU_C must follow Linux HWCAP"); + static_assert(CPU_V == HWCAP_ISA_V, "Flag CPU_V must follow Linux HWCAP"); + + // RISC-V has four bit-manipulation ISA-extensions: Zba/Zbb/Zbc/Zbs. + // Availability for those extensions could not be queried from HWCAP. + // TODO: Add proper detection for those extensions. + _features = auxv & ( + HWCAP_ISA_I | + HWCAP_ISA_M | + HWCAP_ISA_A | + HWCAP_ISA_F | + HWCAP_ISA_D | + HWCAP_ISA_C | + HWCAP_ISA_V); + + if (FILE *f = fopen("/proc/cpuinfo", "r")) { + char buf[512], *p; + while (fgets(buf, sizeof (buf), f) != NULL) { + if ((p = strchr(buf, ':')) != NULL) { + if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) { + char* uarch = os::strdup(p + 2); + uarch[strcspn(uarch, "\n")] = '\0'; + _uarch = uarch; + break; + } + } + } + fclose(f); + } +} diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index 53b017d221725486a1b41944092e99d30565aa49..26ec71d258a1f4c87b973329fbf289482dd8e7ec 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.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. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -304,7 +304,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; if (nm != NULL && nm->has_unsafe_access()) { - // We don't really need a stub here! Just set the pending exeption and + // We don't really need a stub here! Just set the pending exception and // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); @@ -329,7 +329,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, } else if ((thread->thread_state() == _thread_in_vm || thread->thread_state() == _thread_in_native) && sig == SIGBUS && thread->doing_unsafe_access()) { - // We don't really need a stub here! Just set the pending exeption and + // We don't really need a stub here! Just set the pending exception and // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); 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_x86/assembler_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/assembler_windows_x86.cpp index 8045f792b7669efb43117b5cfbe81b5f110c23a9..3cc0003cd4c173c887df6394fad4423e54f8d06f 100644 --- a/src/hotspot/os_cpu/windows_x86/assembler_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/assembler_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, 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 @@ -47,7 +47,7 @@ void MacroAssembler::int3() { // Warning: This mechanism assumes that we only attempt to get the // thread when we are nested below a call wrapper. // -// movl reg, fs:[0] Get exeception pointer +// movl reg, fs:[0] Get exception pointer // movl reg, [reg + thread_ptr_offset] Load thread // void MacroAssembler::get_thread(Register thread) { diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 274e623ea61872c9072d240a718f5a445064b3ed..ba65dd706fb251bf3a7ca03f9f5e72ad408f58d3 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 @@ -4212,7 +4212,7 @@ bool MatchRule::is_vector() const { "CMoveVD", "CMoveVF", "DivVF","DivVD", "AbsVB","AbsVS","AbsVI","AbsVL","AbsVF","AbsVD", - "NegVF","NegVD","NegVI", + "NegVF","NegVD","NegVI","NegVL", "SqrtVD","SqrtVF", "AndV" ,"XorV" ,"OrV", "MaxV", "MinV", @@ -4239,6 +4239,7 @@ bool MatchRule::is_vector() const { "FmaVD","FmaVF","PopCountVI", "PopCountVL", "VectorLongToMask", // Next are vector mask ops. "MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast", + "RoundVF", "RoundVD", // Next are not supported currently. "PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D", "ExtractB","ExtractUB","ExtractC","ExtractS","ExtractI","ExtractL","ExtractF","ExtractD" diff --git a/src/hotspot/share/asm/register.hpp b/src/hotspot/share/asm/register.hpp index 4207267ebab765e8a9deb354973a3280c55492f3..b8538e4df6810330e02f798b8baa4404f4d80c87 100644 --- a/src/hotspot/share/asm/register.hpp +++ b/src/hotspot/share/asm/register.hpp @@ -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; @@ -86,6 +87,149 @@ const type name = ((type)value) #define INTERNAL_VISIBILITY #endif +template class RegSetIterator; +template class ReverseRegSetIterator; + +// 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_CFGPrinter.cpp b/src/hotspot/share/c1/c1_CFGPrinter.cpp index 73a1d2d649e8686330a3a4f7bab3b3d48c867f14..f3b24e9ecb6b34d58e22703458b11227793410e4 100644 --- a/src/hotspot/share/c1/c1_CFGPrinter.cpp +++ b/src/hotspot/share/c1/c1_CFGPrinter.cpp @@ -244,13 +244,11 @@ void CFGPrinterOutput::print_block(BlockBegin* block) { output()->cr(); output()->indent(); + output()->print("successors "); if (block->end() != NULL) { - output()->print("successors "); for (i = 0; i < block->number_of_sux(); i++) { output()->print("\"B%d\" ", block->sux_at(i)->block_id()); } - } else { - output()->print("(block has no end, cannot print successors)"); } output()->cr(); diff --git a/src/hotspot/share/c1/c1_CodeStubs.hpp b/src/hotspot/share/c1/c1_CodeStubs.hpp index 63d44d7a7b69922a0805043a9e7f478ed4ff95dd..97bb9d60377d08d651fffe4388b57b9a36a2c35b 100644 --- a/src/hotspot/share/c1/c1_CodeStubs.hpp +++ b/src/hotspot/share/c1/c1_CodeStubs.hpp @@ -513,9 +513,6 @@ class SimpleExceptionStub: public CodeStub { class ArrayStoreExceptionStub: public SimpleExceptionStub { - private: - CodeEmitInfo* _info; - public: ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {} #ifndef PRODUCT diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index ac415edb1f5dc3ed96b14c0ed8fdcdf364b631b4..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; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index d27b9175c9da514cfceffa758b7ded5d894188c9..33f0a59c7585def5593aa115f832135af5e4a243 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.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 @@ -186,7 +186,6 @@ bool LIR_Opr::is_oop() const { void LIR_Op2::verify() const { #ifdef ASSERT switch (code()) { - case lir_cmove: case lir_xchg: break; @@ -237,8 +236,7 @@ void LIR_Op2::verify() const { LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BlockBegin* block) - : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) - , _cond(cond) + : LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) , _label(block->label()) , _block(block) , _ublock(NULL) @@ -246,8 +244,7 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BlockBegin* block) } LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, CodeStub* stub) : - LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) - , _cond(cond) + LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) , _label(stub->entry()) , _block(NULL) , _ublock(NULL) @@ -255,8 +252,7 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, CodeStub* stub) : } LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BlockBegin* block, BlockBegin* ublock) - : LIR_Op(lir_cond_float_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) - , _cond(cond) + : LIR_Op2(lir_cond_float_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) , _label(block->label()) , _block(block) , _ublock(ublock) @@ -278,13 +274,13 @@ void LIR_OpBranch::change_ublock(BlockBegin* b) { } void LIR_OpBranch::negate_cond() { - switch (_cond) { - case lir_cond_equal: _cond = lir_cond_notEqual; break; - case lir_cond_notEqual: _cond = lir_cond_equal; break; - case lir_cond_less: _cond = lir_cond_greaterEqual; break; - case lir_cond_lessEqual: _cond = lir_cond_greater; break; - case lir_cond_greaterEqual: _cond = lir_cond_less; break; - case lir_cond_greater: _cond = lir_cond_lessEqual; break; + switch (cond()) { + case lir_cond_equal: set_cond(lir_cond_notEqual); break; + case lir_cond_notEqual: set_cond(lir_cond_equal); break; + case lir_cond_less: set_cond(lir_cond_greaterEqual); break; + case lir_cond_lessEqual: set_cond(lir_cond_greater); break; + case lir_cond_greaterEqual: set_cond(lir_cond_less); break; + case lir_cond_greater: set_cond(lir_cond_lessEqual); break; default: ShouldNotReachHere(); } } @@ -507,6 +503,13 @@ void LIR_OpVisitState::visit(LIR_Op* op) { assert(op->as_OpBranch() != NULL, "must be"); LIR_OpBranch* opBranch = (LIR_OpBranch*)op; + assert(opBranch->_tmp1->is_illegal() && opBranch->_tmp2->is_illegal() && + opBranch->_tmp3->is_illegal() && opBranch->_tmp4->is_illegal() && + opBranch->_tmp5->is_illegal(), "not used"); + + if (opBranch->_opr1->is_valid()) do_input(opBranch->_opr1); + if (opBranch->_opr2->is_valid()) do_input(opBranch->_opr2); + if (opBranch->_info != NULL) do_info(opBranch->_info); assert(opBranch->_result->is_illegal(), "not used"); if (opBranch->_stub != NULL) opBranch->stub()->visit(this); @@ -595,17 +598,19 @@ void LIR_OpVisitState::visit(LIR_Op* op) { // to the result operand, otherwise the backend fails case lir_cmove: { - assert(op->as_Op2() != NULL, "must be"); - LIR_Op2* op2 = (LIR_Op2*)op; + assert(op->as_Op4() != NULL, "must be"); + LIR_Op4* op4 = (LIR_Op4*)op; - assert(op2->_info == NULL && op2->_tmp1->is_illegal() && op2->_tmp2->is_illegal() && - op2->_tmp3->is_illegal() && op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used"); - assert(op2->_opr1->is_valid() && op2->_opr2->is_valid() && op2->_result->is_valid(), "used"); + assert(op4->_info == NULL && op4->_tmp1->is_illegal() && op4->_tmp2->is_illegal() && + op4->_tmp3->is_illegal() && op4->_tmp4->is_illegal() && op4->_tmp5->is_illegal(), "not used"); + assert(op4->_opr1->is_valid() && op4->_opr2->is_valid() && op4->_result->is_valid(), "used"); - do_input(op2->_opr1); - do_input(op2->_opr2); - do_temp(op2->_opr2); - do_output(op2->_result); + do_input(op4->_opr1); + do_input(op4->_opr2); + if (op4->_opr3->is_valid()) do_input(op4->_opr3); + if (op4->_opr4->is_valid()) do_input(op4->_opr4); + do_temp(op4->_opr2); + do_output(op4->_result); break; } @@ -1049,6 +1054,10 @@ void LIR_Op3::emit_code(LIR_Assembler* masm) { masm->emit_op3(this); } +void LIR_Op4::emit_code(LIR_Assembler* masm) { + masm->emit_op4(this); +} + void LIR_OpLock::emit_code(LIR_Assembler* masm) { masm->emit_lock(this); if (stub()) { @@ -1089,6 +1098,10 @@ LIR_List::LIR_List(Compilation* compilation, BlockBegin* block) , _file(NULL) , _line(0) #endif +#ifdef RISCV + , _cmp_opr1(LIR_OprFact::illegalOpr) + , _cmp_opr2(LIR_OprFact::illegalOpr) +#endif { } @@ -1106,6 +1119,38 @@ void LIR_List::set_file_and_line(const char * file, int line) { } #endif +#ifdef RISCV +void LIR_List::set_cmp_oprs(LIR_Op* op) { + switch (op->code()) { + case lir_cmp: + _cmp_opr1 = op->as_Op2()->in_opr1(); + _cmp_opr2 = op->as_Op2()->in_opr2(); + break; + case lir_branch: // fall through + case lir_cond_float_branch: + assert(op->as_OpBranch()->cond() == lir_cond_always || + (_cmp_opr1 != LIR_OprFact::illegalOpr && _cmp_opr2 != LIR_OprFact::illegalOpr), + "conditional branches must have legal operands"); + if (op->as_OpBranch()->cond() != lir_cond_always) { + op->as_Op2()->set_in_opr1(_cmp_opr1); + op->as_Op2()->set_in_opr2(_cmp_opr2); + } + break; + case lir_cmove: + op->as_Op4()->set_in_opr3(_cmp_opr1); + op->as_Op4()->set_in_opr4(_cmp_opr2); + break; +#if INCLUDE_ZGC + case lir_zloadbarrier_test: + _cmp_opr1 = FrameMap::as_opr(t1); + _cmp_opr2 = LIR_OprFact::intConst(0); + break; +#endif + default: + break; + } +} +#endif void LIR_List::append(LIR_InsertionBuffer* buffer) { assert(this == buffer->lir_list(), "wrong lir list"); @@ -1677,7 +1722,6 @@ const char * LIR_Op::name() const { case lir_cmp_l2i: s = "cmp_l2i"; break; case lir_ucmp_fd2i: s = "ucomp_fd2i"; break; case lir_cmp_fd2i: s = "comp_fd2i"; break; - case lir_cmove: s = "cmove"; break; case lir_add: s = "add"; break; case lir_sub: s = "sub"; break; case lir_mul: s = "mul"; break; @@ -1700,6 +1744,8 @@ const char * LIR_Op::name() const { case lir_irem: s = "irem"; break; case lir_fmad: s = "fmad"; break; case lir_fmaf: s = "fmaf"; break; + // LIR_Op4 + case lir_cmove: s = "cmove"; break; // LIR_OpJavaCall case lir_static_call: s = "static"; break; case lir_optvirtual_call: s = "optvirtual"; break; @@ -1833,6 +1879,8 @@ void LIR_Op1::print_patch_code(outputStream* out, LIR_PatchCode code) { // LIR_OpBranch void LIR_OpBranch::print_instr(outputStream* out) const { print_condition(out, cond()); out->print(" "); + in_opr1()->print(out); out->print(" "); + in_opr2()->print(out); out->print(" "); if (block() != NULL) { out->print("[B%d] ", block()->block_id()); } else if (stub() != NULL) { @@ -1913,7 +1961,7 @@ void LIR_OpRoundFP::print_instr(outputStream* out) const { // LIR_Op2 void LIR_Op2::print_instr(outputStream* out) const { - if (code() == lir_cmove || code() == lir_cmp) { + if (code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch) { print_condition(out, condition()); out->print(" "); } in_opr1()->print(out); out->print(" "); @@ -1964,6 +2012,15 @@ void LIR_Op3::print_instr(outputStream* out) const { result_opr()->print(out); } +// LIR_Op4 +void LIR_Op4::print_instr(outputStream* out) const { + print_condition(out, condition()); out->print(" "); + in_opr1()->print(out); out->print(" "); + in_opr2()->print(out); out->print(" "); + in_opr3()->print(out); out->print(" "); + in_opr4()->print(out); out->print(" "); + result_opr()->print(out); +} void LIR_OpLock::print_instr(outputStream* out) const { hdr_opr()->print(out); out->print(" "); diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index c4504b7b8b5cc39d18f37279eff13859faeabb87..c3afd5553a1dc7c59025318ca919aef47a32433c 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.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 @@ -887,6 +887,7 @@ class LIR_Op2; class LIR_OpDelay; class LIR_Op3; class LIR_OpAllocArray; +class LIR_Op4; class LIR_OpCall; class LIR_OpJavaCall; class LIR_OpRTCall; @@ -931,8 +932,6 @@ enum LIR_Code { , lir_null_check , lir_return , lir_leal - , lir_branch - , lir_cond_float_branch , lir_move , lir_convert , lir_alloc_object @@ -943,11 +942,12 @@ enum LIR_Code { , lir_load_klass , end_op1 , begin_op2 + , lir_branch + , lir_cond_float_branch , lir_cmp , lir_cmp_l2i , lir_ucmp_fd2i , lir_cmp_fd2i - , lir_cmove , lir_add , lir_sub , lir_mul @@ -975,6 +975,9 @@ enum LIR_Code { , lir_fmad , lir_fmaf , end_op3 + , begin_op4 + , lir_cmove + , end_op4 , begin_opJavaCall , lir_static_call , lir_optvirtual_call @@ -1011,6 +1014,11 @@ enum LIR_Code { , begin_opAssert , lir_assert , end_opAssert +#ifdef INCLUDE_ZGC + , begin_opZLoadBarrierTest + , lir_zloadbarrier_test + , end_opZLoadBarrierTest +#endif }; @@ -1146,6 +1154,7 @@ class LIR_Op: public CompilationResourceObj { virtual LIR_Op1* as_Op1() { return NULL; } virtual LIR_Op2* as_Op2() { return NULL; } virtual LIR_Op3* as_Op3() { return NULL; } + virtual LIR_Op4* as_Op4() { return NULL; } virtual LIR_OpArrayCopy* as_OpArrayCopy() { return NULL; } virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; } virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; } @@ -1419,45 +1428,6 @@ class LIR_OpRTCall: public LIR_OpCall { }; -class LIR_OpBranch: public LIR_Op { - friend class LIR_OpVisitState; - - private: - LIR_Condition _cond; - Label* _label; - BlockBegin* _block; // if this is a branch to a block, this is the block - BlockBegin* _ublock; // if this is a float-branch, this is the unorderd block - CodeStub* _stub; // if this is a branch to a stub, this is the stub - - public: - LIR_OpBranch(LIR_Condition cond, Label* lbl) - : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL) - , _cond(cond) - , _label(lbl) - , _block(NULL) - , _ublock(NULL) - , _stub(NULL) { } - - LIR_OpBranch(LIR_Condition cond, BlockBegin* block); - LIR_OpBranch(LIR_Condition cond, CodeStub* stub); - - // for unordered comparisons - LIR_OpBranch(LIR_Condition cond, BlockBegin* block, BlockBegin* ublock); - - LIR_Condition cond() const { return _cond; } - Label* label() const { return _label; } - BlockBegin* block() const { return _block; } - BlockBegin* ublock() const { return _ublock; } - CodeStub* stub() const { return _stub; } - - void change_block(BlockBegin* b); - void change_ublock(BlockBegin* b); - void negate_cond(); - - virtual void emit_code(LIR_Assembler* masm); - virtual LIR_OpBranch* as_OpBranch() { return this; } - virtual void print_instr(outputStream* out) const PRODUCT_RETURN; -}; class LIR_OpReturn: public LIR_Op1 { friend class LIR_OpVisitState; @@ -1631,19 +1601,19 @@ class LIR_Op2: public LIR_Op { void verify() const; public: - LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, CodeEmitInfo* info = NULL) + LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, CodeEmitInfo* info = NULL, BasicType type = T_ILLEGAL) : LIR_Op(code, LIR_OprFact::illegalOpr, info) , _fpu_stack_size(0) , _opr1(opr1) , _opr2(opr2) - , _type(T_ILLEGAL) + , _type(type) , _tmp1(LIR_OprFact::illegalOpr) , _tmp2(LIR_OprFact::illegalOpr) , _tmp3(LIR_OprFact::illegalOpr) , _tmp4(LIR_OprFact::illegalOpr) , _tmp5(LIR_OprFact::illegalOpr) , _condition(condition) { - assert(code == lir_cmp || code == lir_assert, "code check"); + assert(code == lir_cmp || code == lir_branch || code == lir_cond_float_branch || code == lir_assert, "code check"); } LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) @@ -1675,7 +1645,7 @@ class LIR_Op2: public LIR_Op { , _tmp4(LIR_OprFact::illegalOpr) , _tmp5(LIR_OprFact::illegalOpr) , _condition(lir_cond_unknown) { - assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); + assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check"); } LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr, @@ -1691,7 +1661,7 @@ class LIR_Op2: public LIR_Op { , _tmp4(tmp4) , _tmp5(tmp5) , _condition(lir_cond_unknown) { - assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); + assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check"); } LIR_Opr in_opr1() const { return _opr1; } @@ -1703,10 +1673,10 @@ class LIR_Op2: public LIR_Op { LIR_Opr tmp4_opr() const { return _tmp4; } LIR_Opr tmp5_opr() const { return _tmp5; } LIR_Condition condition() const { - assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition; + assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch || code() == lir_assert, "only valid for branch and assert"); return _condition; } void set_condition(LIR_Condition condition) { - assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition; + assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch, "only valid for branch"); _condition = condition; } void set_fpu_stack_size(int size) { _fpu_stack_size = size; } @@ -1720,6 +1690,51 @@ class LIR_Op2: public LIR_Op { virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; +class LIR_OpBranch: public LIR_Op2 { + friend class LIR_OpVisitState; + + private: + Label* _label; + BlockBegin* _block; // if this is a branch to a block, this is the block + BlockBegin* _ublock; // if this is a float-branch, this is the unorderd block + CodeStub* _stub; // if this is a branch to a stub, this is the stub + + public: + LIR_OpBranch(LIR_Condition cond, Label* lbl) + : LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL) + , _label(lbl) + , _block(NULL) + , _ublock(NULL) + , _stub(NULL) { } + + LIR_OpBranch(LIR_Condition cond, BlockBegin* block); + LIR_OpBranch(LIR_Condition cond, CodeStub* stub); + + // for unordered comparisons + LIR_OpBranch(LIR_Condition cond, BlockBegin* block, BlockBegin* ublock); + + LIR_Condition cond() const { + return condition(); + } + + void set_cond(LIR_Condition cond) { + set_condition(cond); + } + + Label* label() const { return _label; } + BlockBegin* block() const { return _block; } + BlockBegin* ublock() const { return _ublock; } + CodeStub* stub() const { return _stub; } + + void change_block(BlockBegin* b); + void change_ublock(BlockBegin* b); + void negate_cond(); + + virtual void emit_code(LIR_Assembler* masm); + virtual LIR_OpBranch* as_OpBranch() { return this; } + virtual void print_instr(outputStream* out) const PRODUCT_RETURN; +}; + class LIR_OpAllocArray : public LIR_Op { friend class LIR_OpVisitState; @@ -1783,6 +1798,63 @@ class LIR_Op3: public LIR_Op { virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; +class LIR_Op4: public LIR_Op { + friend class LIR_OpVisitState; + protected: + LIR_Opr _opr1; + LIR_Opr _opr2; + LIR_Opr _opr3; + LIR_Opr _opr4; + BasicType _type; + LIR_Opr _tmp1; + LIR_Opr _tmp2; + LIR_Opr _tmp3; + LIR_Opr _tmp4; + LIR_Opr _tmp5; + LIR_Condition _condition; + + public: + LIR_Op4(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr opr3, LIR_Opr opr4, + LIR_Opr result, BasicType type) + : LIR_Op(code, result, NULL) + , _opr1(opr1) + , _opr2(opr2) + , _opr3(opr3) + , _opr4(opr4) + , _type(type) + , _tmp1(LIR_OprFact::illegalOpr) + , _tmp2(LIR_OprFact::illegalOpr) + , _tmp3(LIR_OprFact::illegalOpr) + , _tmp4(LIR_OprFact::illegalOpr) + , _tmp5(LIR_OprFact::illegalOpr) + , _condition(condition) { + assert(code == lir_cmove, "code check"); + assert(type != T_ILLEGAL, "cmove should have type"); + } + + LIR_Opr in_opr1() const { return _opr1; } + LIR_Opr in_opr2() const { return _opr2; } + LIR_Opr in_opr3() const { return _opr3; } + LIR_Opr in_opr4() const { return _opr4; } + BasicType type() const { return _type; } + LIR_Opr tmp1_opr() const { return _tmp1; } + LIR_Opr tmp2_opr() const { return _tmp2; } + LIR_Opr tmp3_opr() const { return _tmp3; } + LIR_Opr tmp4_opr() const { return _tmp4; } + LIR_Opr tmp5_opr() const { return _tmp5; } + + LIR_Condition condition() const { return _condition; } + void set_condition(LIR_Condition condition) { _condition = condition; } + + void set_in_opr1(LIR_Opr opr) { _opr1 = opr; } + void set_in_opr2(LIR_Opr opr) { _opr2 = opr; } + void set_in_opr3(LIR_Opr opr) { _opr3 = opr; } + void set_in_opr4(LIR_Opr opr) { _opr4 = opr; } + virtual void emit_code(LIR_Assembler* masm); + virtual LIR_Op4* as_Op4() { return this; } + + virtual void print_instr(outputStream* out) const PRODUCT_RETURN; +}; //-------------------------------- class LabelObj: public CompilationResourceObj { @@ -2022,6 +2094,10 @@ class LIR_List: public CompilationResourceObj { const char * _file; int _line; #endif +#ifdef RISCV + LIR_Opr _cmp_opr1; + LIR_Opr _cmp_opr2; +#endif public: void append(LIR_Op* op) { @@ -2034,6 +2110,12 @@ class LIR_List: public CompilationResourceObj { } #endif // PRODUCT +#ifdef RISCV + set_cmp_oprs(op); + // lir_cmp set cmp oprs only on riscv + if (op->code() == lir_cmp) return; +#endif + _operations.append(op); #ifdef ASSERT @@ -2050,6 +2132,10 @@ class LIR_List: public CompilationResourceObj { void set_file_and_line(const char * file, int line); #endif +#ifdef RISCV + void set_cmp_oprs(LIR_Op* op); +#endif + //---------- accessors --------------- LIR_OpList* instructions_list() { return &_operations; } int length() const { return _operations.length(); } @@ -2166,8 +2252,9 @@ class LIR_List: public CompilationResourceObj { void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); - void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { - append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); + void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type, + LIR_Opr cmp_opr1 = LIR_OprFact::illegalOpr, LIR_Opr cmp_opr2 = LIR_OprFact::illegalOpr) { + append(new LIR_Op4(lir_cmove, condition, src1, src2, cmp_opr1, cmp_opr2, dst, type)); } void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index be0a6abc2ca22f1fec53838ec73a3a68b06d3056..331db6487562d4f59ec842ede160c449f9dd772b 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) @@ -691,10 +689,6 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { comp_fl2i(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op); break; - case lir_cmove: - cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type()); - break; - case lir_shl: case lir_shr: case lir_ushr: @@ -756,6 +750,17 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { } } +void LIR_Assembler::emit_op4(LIR_Op4* op) { + switch(op->code()) { + case lir_cmove: + cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type(), op->in_opr3(), op->in_opr4()); + break; + + default: + Unimplemented(); + break; + } +} void LIR_Assembler::build_frame() { _masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp index f27ade60bae2869f06ae8a7d835a9f9ca8843ed1..8a50667c88ab8d40d91f82a02caba383def77038 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; @@ -186,6 +184,7 @@ class LIR_Assembler: public CompilationResourceObj { void emit_op1(LIR_Op1* op); void emit_op2(LIR_Op2* op); void emit_op3(LIR_Op3* op); + void emit_op4(LIR_Op4* op); void emit_opBranch(LIR_OpBranch* op); void emit_opLabel(LIR_OpLabel* op); void emit_arraycopy(LIR_OpArrayCopy* op); @@ -219,8 +218,8 @@ class LIR_Assembler: public CompilationResourceObj { void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); - void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); - + void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1 = LIR_OprFact::illegalOpr, LIR_Opr cmp_opr2 = LIR_OprFact::illegalOpr); void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); void ic_call( LIR_OpJavaCall* op); void vtable_call( LIR_OpJavaCall* op); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index d2386d7cbb6234a9587c432a300f397922751e42..9f0d264f2fa17abd226f3492ac3fb2ba5a4417e6 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.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 @@ -1240,11 +1240,11 @@ void LinearScan::add_register_hints(LIR_Op* op) { break; } case lir_cmove: { - assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2"); - LIR_Op2* cmove = (LIR_Op2*)op; + assert(op->as_Op4() != NULL, "lir_cmove must be LIR_Op4"); + LIR_Op4* cmove = (LIR_Op4*)op; LIR_Opr move_from = cmove->in_opr1(); - LIR_Opr move_to = cmove->result_opr(); + LIR_Opr move_to = cmove->result_opr(); if (move_to->is_register() && move_from->is_register()) { Interval* from = interval_at(reg_num(move_from)); @@ -3131,6 +3131,9 @@ void LinearScan::do_linear_scan() { } } +#ifndef RISCV + // Disable these optimizations on riscv temporarily, because it does not + // work when the comparison operands are bound to branches or cmoves. { TIME_LINEAR_SCAN(timer_optimize_lir); EdgeMoveOptimizer::optimize(ir()->code()); @@ -3138,6 +3141,7 @@ void LinearScan::do_linear_scan() { // check that cfg is still correct after optimizations ir()->verify(); } +#endif NOT_PRODUCT(print_lir(1, "Before Code Generation", false)); NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final)); @@ -6361,14 +6365,14 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { // There might be a cmove inserted for profiling which depends on the same // compare. If we change the condition of the respective compare, we have // to take care of this cmove as well. - LIR_Op2* prev_cmove = NULL; + LIR_Op4* prev_cmove = NULL; for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) { prev_op = instructions->at(j); // check for the cmove if (prev_op->code() == lir_cmove) { - assert(prev_op->as_Op2() != NULL, "cmove must be of type LIR_Op2"); - prev_cmove = (LIR_Op2*)prev_op; + assert(prev_op->as_Op4() != NULL, "cmove must be of type LIR_Op4"); + prev_cmove = (LIR_Op4*)prev_op; assert(prev_branch->cond() == prev_cmove->condition(), "should be the same"); } if (prev_op->code() == lir_cmp) { diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index cb5c0aeb8c78008f044e0d009bddbd102fa38bbb..cff024a8afb905a8da8c1919a77156746cf31230 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 @@ -27,6 +27,7 @@ #include "cds/archiveUtils.hpp" #include "cds/cppVtables.hpp" #include "cds/dumpAllocStats.hpp" +#include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/classLoaderDataShared.hpp" #include "classfile/symbolTable.hpp" @@ -40,6 +41,7 @@ #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" +#include "oops/objArrayOop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "runtime/arguments.hpp" #include "runtime/globals_extension.hpp" @@ -522,7 +524,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) { @@ -928,27 +931,29 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { } // rw/ro regions only - static void write_dump_region(const char* name, DumpRegion* region) { + static void log_metaspace_region(const char* name, DumpRegion* region, + const ArchiveBuilder::SourceObjList* src_objs) { address region_base = address(region->base()); address region_top = address(region->top()); - write_region(name, region_base, region_top, region_base + buffer_to_runtime_delta()); + log_region(name, region_base, region_top, region_base + buffer_to_runtime_delta()); + log_metaspace_objects(region, src_objs); } #define _LOG_PREFIX PTR_FORMAT ": @@ %-17s %d" - static void write_klass(Klass* k, address runtime_dest, const char* type_name, int bytes, Thread* current) { + static void log_klass(Klass* k, address runtime_dest, const char* type_name, int bytes, Thread* current) { ResourceMark rm(current); log_debug(cds, map)(_LOG_PREFIX " %s", p2i(runtime_dest), type_name, bytes, k->external_name()); } - static void write_method(Method* m, address runtime_dest, const char* type_name, int bytes, Thread* current) { + static void log_method(Method* m, address runtime_dest, const char* type_name, int bytes, Thread* current) { ResourceMark rm(current); log_debug(cds, map)(_LOG_PREFIX " %s", p2i(runtime_dest), type_name, bytes, m->external_name()); } // rw/ro regions only - static void write_objects(DumpRegion* region, const ArchiveBuilder::SourceObjList* src_objs) { + static void log_metaspace_objects(DumpRegion* region, const ArchiveBuilder::SourceObjList* src_objs) { address last_obj_base = address(region->base()); address last_obj_end = address(region->base()); address region_end = address(region->end()); @@ -957,7 +962,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { SourceObjInfo* src_info = src_objs->at(i); address src = src_info->orig_obj(); address dest = src_info->dumped_addr(); - write_data(last_obj_base, dest, last_obj_base + buffer_to_runtime_delta()); + log_data(last_obj_base, dest, last_obj_base + buffer_to_runtime_delta()); address runtime_dest = dest + buffer_to_runtime_delta(); int bytes = src_info->size_in_bytes(); @@ -966,21 +971,21 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { switch (type) { case MetaspaceObj::ClassType: - write_klass((Klass*)src, runtime_dest, type_name, bytes, current); + log_klass((Klass*)src, runtime_dest, type_name, bytes, current); break; case MetaspaceObj::ConstantPoolType: - write_klass(((ConstantPool*)src)->pool_holder(), + log_klass(((ConstantPool*)src)->pool_holder(), runtime_dest, type_name, bytes, current); break; case MetaspaceObj::ConstantPoolCacheType: - write_klass(((ConstantPoolCache*)src)->constant_pool()->pool_holder(), + log_klass(((ConstantPoolCache*)src)->constant_pool()->pool_holder(), runtime_dest, type_name, bytes, current); break; case MetaspaceObj::MethodType: - write_method((Method*)src, runtime_dest, type_name, bytes, current); + log_method((Method*)src, runtime_dest, type_name, bytes, current); break; case MetaspaceObj::ConstMethodType: - write_method(((ConstMethod*)src)->method(), runtime_dest, type_name, bytes, current); + log_method(((ConstMethod*)src)->method(), runtime_dest, type_name, bytes, current); break; case MetaspaceObj::SymbolType: { @@ -999,22 +1004,22 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { last_obj_end = dest + bytes; } - write_data(last_obj_base, last_obj_end, last_obj_base + buffer_to_runtime_delta()); + log_data(last_obj_base, last_obj_end, last_obj_base + buffer_to_runtime_delta()); if (last_obj_end < region_end) { log_debug(cds, map)(PTR_FORMAT ": @@ Misc data " SIZE_FORMAT " bytes", p2i(last_obj_end + buffer_to_runtime_delta()), size_t(region_end - last_obj_end)); - write_data(last_obj_end, region_end, last_obj_end + buffer_to_runtime_delta()); + log_data(last_obj_end, region_end, last_obj_end + buffer_to_runtime_delta()); } } #undef _LOG_PREFIX - // Write information about a region, whose address at dump time is [base .. top). At + // Log information about a region, whose address at dump time is [base .. top). At // runtime, this region will be mapped to runtime_base. runtime_base is 0 if this // region will be mapped at os-selected addresses (such as the bitmap region), or will // be accessed with os::read (the header). - static void write_region(const char* name, address base, address top, address runtime_base) { + static void log_region(const char* name, address base, address top, address runtime_base) { size_t size = top - base; base = runtime_base; top = runtime_base + size; @@ -1023,27 +1028,63 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { } // open and closed archive regions - static void write_heap_region(const char* which, GrowableArray *regions) { + static void log_heap_regions(const char* which, GrowableArray *regions) { +#if INCLUDE_CDS_JAVA_HEAP for (int i = 0; i < regions->length(); i++) { address start = address(regions->at(i).start()); address end = address(regions->at(i).end()); - write_region(which, start, end, start); - write_data(start, end, start); + log_region(which, start, end, start); + + while (start < end) { + size_t byte_size; + oop archived_oop = cast_to_oop(start); + oop original_oop = HeapShared::get_original_object(archived_oop); + if (original_oop != NULL) { + ResourceMark rm; + log_info(cds, map)(PTR_FORMAT ": @@ Object %s", + p2i(start), original_oop->klass()->external_name()); + byte_size = original_oop->size() * BytesPerWord; + } else if (archived_oop == HeapShared::roots()) { + // HeapShared::roots() is copied specially so it doesn't exist in + // HeapShared::OriginalObjectTable. See HeapShared::copy_roots(). + log_info(cds, map)(PTR_FORMAT ": @@ Object HeapShared:roots (ObjArray)", + p2i(start)); + byte_size = objArrayOopDesc::object_size(HeapShared::roots()->length()) * BytesPerWord; + } else { + // We have reached the end of the region + break; + } + address oop_end = start + byte_size; + log_data(start, oop_end, start, /*is_heap=*/true); + start = oop_end; + } + if (start < end) { + log_info(cds, map)(PTR_FORMAT ": @@ Unused heap space " SIZE_FORMAT " bytes", + p2i(start), size_t(end - start)); + log_data(start, end, start, /*is_heap=*/true); + } } +#endif } - // Dump all the data [base...top). Pretend that the base address + // Log all the data [base...top). Pretend that the base address // will be mapped to runtime_base at run-time. - static void write_data(address base, address top, address runtime_base) { + static void log_data(address base, address top, address runtime_base, bool is_heap = false) { assert(top >= base, "must be"); LogStreamHandle(Trace, cds, map) lsh; if (lsh.is_enabled()) { - os::print_hex_dump(&lsh, base, top, sizeof(address), 32, runtime_base); + int unitsize = sizeof(address); + if (is_heap && UseCompressedOops) { + // This makes the compressed oop pointers easier to read, but + // longs and doubles will be split into two words. + unitsize = sizeof(narrowOop); + } + os::print_hex_dump(&lsh, base, top, unitsize, 32, runtime_base); } } - static void write_header(FileMapInfo* mapinfo) { + static void log_header(FileMapInfo* mapinfo) { LogStreamHandle(Info, cds, map) lsh; if (lsh.is_enabled()) { mapinfo->print(&lsh); @@ -1051,41 +1092,38 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { } public: - static void write(ArchiveBuilder* builder, FileMapInfo* mapinfo, - GrowableArray *closed_heap_regions, - GrowableArray *open_heap_regions, - char* bitmap, size_t bitmap_size_in_bytes) { + static void log(ArchiveBuilder* builder, FileMapInfo* mapinfo, + GrowableArray *closed_heap_regions, + GrowableArray *open_heap_regions, + char* bitmap, size_t bitmap_size_in_bytes) { log_info(cds, map)("%s CDS archive map for %s", DumpSharedSpaces ? "Static" : "Dynamic", mapinfo->full_path()); address header = address(mapinfo->header()); address header_end = header + mapinfo->header()->header_size(); - write_region("header", header, header_end, 0); - write_header(mapinfo); - write_data(header, header_end, 0); + log_region("header", header, header_end, 0); + log_header(mapinfo); + log_data(header, header_end, 0); DumpRegion* rw_region = &builder->_rw_region; DumpRegion* ro_region = &builder->_ro_region; - write_dump_region("rw region", rw_region); - write_objects(rw_region, &builder->_rw_src_objs); - - write_dump_region("ro region", ro_region); - write_objects(ro_region, &builder->_ro_src_objs); + log_metaspace_region("rw region", rw_region, &builder->_rw_src_objs); + log_metaspace_region("ro region", ro_region, &builder->_ro_src_objs); address bitmap_end = address(bitmap + bitmap_size_in_bytes); - write_region("bitmap", address(bitmap), bitmap_end, 0); - write_data(header, header_end, 0); + log_region("bitmap", address(bitmap), bitmap_end, 0); + log_data((address)bitmap, bitmap_end, 0); if (closed_heap_regions != NULL) { - write_heap_region("closed heap region", closed_heap_regions); + log_heap_regions("closed heap region", closed_heap_regions); } if (open_heap_regions != NULL) { - write_heap_region("open heap region", open_heap_regions); + log_heap_regions("open heap region", open_heap_regions); } log_info(cds, map)("[End of CDS archive map]"); } -}; +}; // end ArchiveBuilder::CDSMapLogger void ArchiveBuilder::print_stats() { _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used())); @@ -1139,9 +1177,10 @@ void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, } if (log_is_enabled(Info, cds, map)) { - CDSMapLogger::write(this, mapinfo, closed_heap_regions, open_heap_regions, - bitmap, bitmap_size_in_bytes); + CDSMapLogger::log(this, mapinfo, closed_heap_regions, open_heap_regions, + bitmap, bitmap_size_in_bytes); } + CDS_JAVA_HEAP_ONLY(HeapShared::destroy_archived_object_cache()); FREE_C_HEAP_ARRAY(char, bitmap); } 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/dumpTimeClassInfo.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.hpp index 80f6d81442c6d407c560ed29313be34286001407..5b4f5cd9b9beb1f494c5a2a68b8fba2aae757657 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.hpp @@ -167,7 +167,8 @@ public: 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(); @@ -175,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 7901ab855ce891e0ed4aeffba19c1b187a5bf802..efa0fd8275ad07a5e293abb72317b559a2fb7627 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -166,10 +166,9 @@ template static void get_header_version(char (&header_version) [N]) { assert(header_version[JVM_IDENT_MAX-1] == 0, "must be"); } -FileMapInfo::FileMapInfo(const char* full_path, bool is_static) { - memset((void*)this, 0, sizeof(FileMapInfo)); - _full_path = full_path; - _is_static = is_static; +FileMapInfo::FileMapInfo(const char* full_path, bool is_static) : + _is_static(is_static), _file_open(false), _is_mapped(false), _fd(-1), _file_offset(0), + _full_path(full_path), _base_archive_name(nullptr), _header(nullptr) { if (_is_static) { assert(_current_info == NULL, "must be singleton"); // not thread safe _current_info = this; @@ -177,8 +176,6 @@ FileMapInfo::FileMapInfo(const char* full_path, bool is_static) { assert(_dynamic_archive_info == NULL, "must be singleton"); // not thread safe _dynamic_archive_info = this; } - _file_offset = 0; - _file_open = false; } FileMapInfo::~FileMapInfo() { @@ -189,6 +186,11 @@ FileMapInfo::~FileMapInfo() { assert(_dynamic_archive_info == this, "must be singleton"); // not thread safe _dynamic_archive_info = NULL; } + + if (_header != nullptr) { + os::free(_header); + } + if (_file_open) { ::close(_fd); } @@ -1108,6 +1110,9 @@ public: } ~FileHeaderHelper() { + if (_header != nullptr) { + FREE_C_HEAP_ARRAY(char, _header); + } if (_fd != -1) { ::close(_fd); } @@ -2327,6 +2332,11 @@ void FileMapInfo::fixup_mapped_heap_regions() { "Null closed_heap_regions array with non-zero count"); G1CollectedHeap::heap()->fill_archive_regions(closed_heap_regions, num_closed_heap_regions); + // G1 marking uses the BOT for object chunking during marking in + // G1CMObjArrayProcessor::process_slice(); for this reason we need to + // initialize the BOT for closed archive regions too. + G1CollectedHeap::heap()->populate_archive_regions_bot_part(closed_heap_regions, + num_closed_heap_regions); } // do the same for mapped open archive heap regions @@ -2339,11 +2349,6 @@ void FileMapInfo::fixup_mapped_heap_regions() { // fast G1BlockOffsetTablePart::block_start operations for any given address // within the open archive regions when trying to find start of an object // (e.g. during card table scanning). - // - // This is only needed for open archive regions but not the closed archive - // regions, because objects in closed archive regions never reference objects - // outside the closed archive regions and they are immutable. So we never - // need their BOT during garbage collection. G1CollectedHeap::heap()->populate_archive_regions_bot_part(open_heap_regions, num_open_heap_regions); } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 26a852b01589a804cf76409c7844a3cbaf7ff272..fa387a73d1d91def1cebf146c468625269138c71 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -51,8 +51,9 @@ #include "memory/universe.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/fieldStreams.inline.hpp" -#include "oops/objArrayOop.hpp" +#include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/typeArrayOop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/globals_extension.hpp" @@ -213,6 +214,7 @@ void HeapShared::reset_archived_object_states(TRAPS) { } HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL; +HeapShared::OriginalObjectTable* HeapShared::_original_object_table = NULL; oop HeapShared::find_archived_heap_object(oop obj) { assert(DumpSharedSpaces, "dump-time only"); ArchivedObjectCache* cache = archived_object_cache(); @@ -317,6 +319,9 @@ oop HeapShared::archive_object(oop obj) { ArchivedObjectCache* cache = archived_object_cache(); CachedOopInfo info = make_cached_oop_info(archived_oop); cache->put(obj, info); + if (_original_object_table != NULL) { + _original_object_table->put(archived_oop, obj); + } if (log_is_enabled(Debug, cds, heap)) { ResourceMark rm; log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT " : %s", @@ -466,7 +471,7 @@ void HeapShared::archive_objects(GrowableArray* closed_regions, NoSafepointVerifier nsv; // Cache for recording where the archived objects are copied to - create_archived_object_cache(); + create_archived_object_cache(log_is_enabled(Info, cds, map)); log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]", UseCompressedOops ? p2i(CompressedOops::begin()) : @@ -480,7 +485,6 @@ void HeapShared::archive_objects(GrowableArray* closed_regions, copy_open_objects(open_regions); CDSHeapVerifier::verify(); - destroy_archived_object_cache(); } G1HeapVerifier::verify_archive_regions(); @@ -532,6 +536,12 @@ void HeapShared::copy_open_objects(GrowableArray* open_regions) { // Copy _pending_archive_roots into an objArray void HeapShared::copy_roots() { + // HeapShared::roots() points into an ObjArray in the open archive region. A portion of the + // objects in this array are discovered during HeapShared::archive_objects(). For example, + // in HeapShared::archive_reachable_objects_from() -> HeapShared::check_enum_obj(). + // However, HeapShared::archive_objects() happens inside a safepoint, so we can't + // allocate a "regular" ObjArray and pass the result to HeapShared::archive_object(). + // Instead, we have to roll our own alloc/copy routine here. int length = _pending_roots != NULL ? _pending_roots->length() : 0; size_t size = objArrayOopDesc::object_size(length); Klass* k = Universe::objectArrayKlassObj(); // already relocated to point to archived klass @@ -574,7 +584,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; @@ -582,8 +592,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; } @@ -744,7 +753,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); } diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 74d1f1b6e7eb8c2531bbf82ffad9828bedad5671..402f451de4c7bde2190113ee59768f8a48e0fbd0 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" @@ -246,23 +247,25 @@ private: } 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); - } + typedef ResourceHashtable OriginalObjectTable; + static OriginalObjectTable* _original_object_table; class DumpTimeKlassSubGraphInfoTable : public ResourceHashtable { + DumpTimeSharedClassTable_hash> { public: int _count; }; @@ -379,17 +382,36 @@ private: static void fill_failed_loaded_region(); public: static void reset_archived_object_states(TRAPS); - static void create_archived_object_cache() { + static void create_archived_object_cache(bool create_orig_table) { _archived_object_cache = new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache(); + if (create_orig_table) { + _original_object_table = + new (ResourceObj::C_HEAP, mtClass)OriginalObjectTable(); + } else { + _original_object_table = NULL; + } } static void destroy_archived_object_cache() { delete _archived_object_cache; _archived_object_cache = NULL; + if (_original_object_table != NULL) { + delete _original_object_table; + _original_object_table = NULL; + } } static ArchivedObjectCache* archived_object_cache() { return _archived_object_cache; } + static oop get_original_object(oop archived_object) { + assert(_original_object_table != NULL, "sanity"); + oop* r = _original_object_table->get(archived_object); + if (r == NULL) { + return NULL; + } else { + return *r; + } + } static oop find_archived_heap_object(oop obj); static oop archive_object(oop obj); diff --git a/src/hotspot/share/ci/ciSymbols.hpp b/src/hotspot/share/ci/ciSymbols.hpp index df77b90148fdbe1207c336f5ff19e96d3a060dd3..244d7196cced253382490e9dfca3deb1805da00c 100644 --- a/src/hotspot/share/ci/ciSymbols.hpp +++ b/src/hotspot/share/ci/ciSymbols.hpp @@ -40,4 +40,4 @@ class ciSymbols { }; -#endif // SHARE_CI_CISYMBOLS_HPP \ No newline at end of file +#endif // SHARE_CI_CISYMBOLS_HPP diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index 6ce6325cf91ff371aa4f643a3e84caf77f6e2328..e4ffd7dd9fe16719080af67dc347d938d9b5b2f1 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -2460,7 +2460,7 @@ int ciTypeFlow::profiled_count(ciTypeFlow::Loop* loop) { return 0; } ciTypeFlow::Block* tail = loop->tail(); - if (tail->control() == -1) { + if (tail->control() == -1 || tail->has_trap()) { return 0; } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index ae76dea73aa8fb73429e104aa9f0d814ef6bb41e..51596a02a12b5cac702603d722b2216c62c93e49 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -454,16 +454,18 @@ char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) { } char *native_platform_string; - { JavaThread* thread = THREAD; - jstring js = (jstring) JNIHandles::make_local(thread, java_string()); - bool is_copy; + JavaThread* thread = THREAD; + jstring js = (jstring) JNIHandles::make_local(thread, java_string()); + { HandleMark hm(thread); ThreadToNativeFromVM ttn(thread); JNIEnv *env = thread->jni_environment(); + bool is_copy; native_platform_string = (_to_platform_string_fn)(env, js, &is_copy); assert(is_copy == JNI_TRUE, "is_copy value changed"); - JNIHandles::destroy_local(js); } + JNIHandles::destroy_local(js); + return native_platform_string; } 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..b2757ca86bc856dc520822f0b942214e0a235759 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,6 +134,7 @@ class methodHandle; do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \ do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \ do_name(floor_name, "floor") do_name(ceil_name, "ceil") do_name(rint_name, "rint") \ + do_name(round_name, "round") \ \ do_name(addExact_name,"addExact") \ do_name(decrementExact_name,"decrementExact") \ @@ -185,6 +186,8 @@ class methodHandle; do_intrinsic(_minF, java_lang_Math, min_name, float2_float_signature, F_S) \ do_intrinsic(_maxD, java_lang_Math, max_name, double2_double_signature, F_S) \ do_intrinsic(_minD, java_lang_Math, min_name, double2_double_signature, F_S) \ + do_intrinsic(_roundD, java_lang_Math, round_name, double_long_signature, F_S) \ + do_intrinsic(_roundF, java_lang_Math, round_name, float_int_signature, F_S) \ do_intrinsic(_dcopySign, java_lang_Math, copySign_name, double2_double_signature, F_S) \ do_intrinsic(_fcopySign, java_lang_Math, copySign_name, float2_float_signature, F_S) \ do_intrinsic(_dsignum, java_lang_Math, signum_name, double_double_signature, F_S) \ @@ -354,9 +357,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 +462,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 e0402392467e2b9c9a19196798b5d755e569844e..f08afd2ce767326db10b7e08ce95bb4feb438037 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -465,8 +465,6 @@ template(security_manager_signature, "Ljava/lang/SecurityManager;") \ template(defineOrCheckPackage_name, "defineOrCheckPackage") \ template(defineOrCheckPackage_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \ - template(fileToEncodedURL_name, "fileToEncodedURL") \ - template(fileToEncodedURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \ template(getProtectionDomain_name, "getProtectionDomain") \ template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ template(java_lang_Integer_array_signature, "[Ljava/lang/Integer;") \ @@ -561,6 +559,7 @@ template(char_array_void_signature, "([C)V") \ template(int_int_void_signature, "(II)V") \ template(long_long_void_signature, "(JJ)V") \ + template(void_byte_array_signature, "()[B") \ template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \ template(void_object_signature, "()Ljava/lang/Object;") \ template(void_class_signature, "()Ljava/lang/Class;") \ @@ -683,7 +682,6 @@ template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \ do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \ template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \ - template(serializePropertiesToByteArray_signature, "()[B") \ template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \ template(classRedefinedCount_name, "classRedefinedCount") \ template(classLoader_name, "classLoader") \ diff --git a/src/hotspot/share/code/debugInfo.hpp b/src/hotspot/share/code/debugInfo.hpp index 3f213783a218afc6b24effa529fde4e9e0630d15..7c85ae60c33fa66d905dbb4e0271143eaa47d602 100644 --- a/src/hotspot/share/code/debugInfo.hpp +++ b/src/hotspot/share/code/debugInfo.hpp @@ -29,7 +29,6 @@ #include "code/location.hpp" #include "code/nmethod.hpp" #include "code/oopRecorder.hpp" -#include "runtime/stackValue.hpp" #include "runtime/thread.hpp" #include "utilities/growableArray.hpp" diff --git a/src/hotspot/share/code/exceptionHandlerTable.cpp b/src/hotspot/share/code/exceptionHandlerTable.cpp index f3c2a7870445877fb5fb7bd8d82b6b914393d815..d43d18e4b2b53cdc30a8044dd6833c1be38ed801 100644 --- a/src/hotspot/share/code/exceptionHandlerTable.cpp +++ b/src/hotspot/share/code/exceptionHandlerTable.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 @@ -68,7 +68,7 @@ ExceptionHandlerTable::ExceptionHandlerTable(int initial_size) { ExceptionHandlerTable::ExceptionHandlerTable(const CompiledMethod* cm) { _table = (HandlerTableEntry*)cm->handler_table_begin(); _length = cm->handler_table_size() / sizeof(HandlerTableEntry); - _size = 0; // no space allocated by ExeptionHandlerTable! + _size = 0; // no space allocated by ExceptionHandlerTable! } diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index aa8dd0a1be8638c9bc4519177af24624da36744c..1bbff8fb77bcc5ce45d9ba52ca11aec1ad321da2 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -124,10 +124,17 @@ intx CompilerConfig::scaled_freq_log(intx freq_log) { // Returns threshold scaled with the value of scale. // If scale < 0.0, threshold is returned without scaling. intx CompilerConfig::scaled_compile_threshold(intx threshold, double scale) { + assert(threshold >= 0, "must be"); if (scale == 1.0 || scale < 0.0) { return threshold; } else { - return (intx)(threshold * scale); + double v = threshold * scale; + assert(v >= 0, "must be"); + if (v > max_intx) { + return max_intx; + } else { + return (intx)(v); + } } } diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.cpp b/src/hotspot/share/gc/g1/g1BarrierSet.cpp index 994bf16c2e30b5e816c2b5ea41d36ed6f25f11ab..a04c7370518df6b06ea419fa1faaf2c2c7be8bc4 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp @@ -61,13 +61,6 @@ G1BarrierSet::G1BarrierSet(G1CardTable* card_table) : _dirty_card_queue_set(&_dirty_card_queue_buffer_allocator) {} -void G1BarrierSet::enqueue(oop pre_val) { - // Nulls should have been already filtered. - assert(oopDesc::is_oop(pre_val, true), "Error"); - SATBMarkQueue& queue = G1ThreadLocalData::satb_mark_queue(Thread::current()); - G1BarrierSet::satb_mark_queue_set().enqueue(queue, pre_val); -} - template void G1BarrierSet::write_ref_array_pre_work(T* dst, size_t count) { G1SATBMarkQueueSet& queue_set = G1BarrierSet::satb_mark_queue_set(); diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index e8eb6e9c9d1dfe252999693f54b7b66b0ae04798..d90d83298c9d2a1036ca04109c1eb39806766c97 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -56,10 +56,12 @@ class G1BarrierSet: public CardTableBarrierSet { } // Add "pre_val" to a set of objects that may have been disconnected from the - // pre-marking object graph. - static void enqueue(oop pre_val); + // pre-marking object graph. Prefer the version that takes location, as it + // can avoid touching the heap unnecessarily. + template static void enqueue(T* dst); + static void enqueue_preloaded(oop pre_val); - static void enqueue_if_weak(DecoratorSet decorators, oop value); + static void enqueue_preloaded_if_weak(DecoratorSet decorators, oop value); template void write_ref_array_pre_work(T* dst, size_t count); virtual void write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized); diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp index 8fa29544ca4338a99fbb3aac848d242b312ad827..f7a6fd3ee5a37a052058a818b9c0ddc9868b2e3c 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp @@ -28,11 +28,35 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1CardTable.hpp" +#include "gc/g1/g1ThreadLocalData.hpp" #include "gc/shared/accessBarrierSupport.inline.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.hpp" +inline void G1BarrierSet::enqueue_preloaded(oop pre_val) { + // Nulls should have been already filtered. + assert(oopDesc::is_oop(pre_val, true), "Error"); + + G1SATBMarkQueueSet& queue_set = G1BarrierSet::satb_mark_queue_set(); + if (!queue_set.is_active()) return; + + SATBMarkQueue& queue = G1ThreadLocalData::satb_mark_queue(Thread::current()); + queue_set.enqueue_known_active(queue, pre_val); +} + +template +inline void G1BarrierSet::enqueue(T* dst) { + G1SATBMarkQueueSet& queue_set = G1BarrierSet::satb_mark_queue_set(); + if (!queue_set.is_active()) return; + + T heap_oop = RawAccess::oop_load(dst); + if (!CompressedOops::is_null(heap_oop)) { + SATBMarkQueue& queue = G1ThreadLocalData::satb_mark_queue(Thread::current()); + queue_set.enqueue_known_active(queue, CompressedOops::decode_not_null(heap_oop)); + } +} + template inline void G1BarrierSet::write_ref_field_pre(T* field) { if (HasDecorator::value || @@ -40,10 +64,7 @@ inline void G1BarrierSet::write_ref_field_pre(T* field) { return; } - T heap_oop = RawAccess::oop_load(field); - if (!CompressedOops::is_null(heap_oop)) { - enqueue(CompressedOops::decode_not_null(heap_oop)); - } + enqueue(field); } template @@ -55,7 +76,7 @@ inline void G1BarrierSet::write_ref_field_post(T* field, oop new_val) { } } -inline void G1BarrierSet::enqueue_if_weak(DecoratorSet decorators, oop value) { +inline void G1BarrierSet::enqueue_preloaded_if_weak(DecoratorSet decorators, oop value) { assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); // Loading from a weak or phantom reference needs enqueueing, as // the object may not have been reachable (part of the snapshot) @@ -65,7 +86,7 @@ inline void G1BarrierSet::enqueue_if_weak(DecoratorSet decorators, oop value) { const bool needs_enqueue = (!peek && !on_strong_oop_ref); if (needs_enqueue && value != NULL) { - enqueue(value); + enqueue_preloaded(value); } } @@ -74,7 +95,7 @@ template inline oop G1BarrierSet::AccessBarrier:: oop_load_not_in_heap(T* addr) { oop value = ModRef::oop_load_not_in_heap(addr); - enqueue_if_weak(decorators, value); + enqueue_preloaded_if_weak(decorators, value); return value; } @@ -83,7 +104,7 @@ template inline oop G1BarrierSet::AccessBarrier:: oop_load_in_heap(T* addr) { oop value = ModRef::oop_load_in_heap(addr); - enqueue_if_weak(decorators, value); + enqueue_preloaded_if_weak(decorators, value); return value; } @@ -91,7 +112,7 @@ template inline oop G1BarrierSet::AccessBarrier:: oop_load_in_heap_at(oop base, ptrdiff_t offset) { oop value = ModRef::oop_load_in_heap_at(base, offset); - enqueue_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); + enqueue_preloaded_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); return value; } 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 a87db1ff71849645596a636daa06b2c005ca9794..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,93 +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"); - _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; } } @@ -438,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) { @@ -490,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; } @@ -591,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. @@ -627,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); @@ -639,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) { @@ -718,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; } @@ -727,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); } @@ -759,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: @@ -813,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 { @@ -844,7 +841,7 @@ public: }; template class CardOrRanges> -class G1CardSetContainersClosure : public G1CardSet::CardSetPtrClosure { +class G1CardSetContainersClosure : public G1CardSet::ContainerPtrClosure { G1CardSet* _card_set; Closure& _cl; @@ -855,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); } }; @@ -879,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 4f861baf4eb41915271345dc86a81421234ad9ce..453594da3f9e570d0ad7da90999cd5bb544c14e7 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp @@ -30,13 +30,8 @@ #include "runtime/atomic.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 13e70302b023e97e4e8349327af639082de7f515..3949687a97c2fefabd10abefe252d284564844d4 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -29,8 +29,9 @@ #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); @@ -43,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) { @@ -63,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; } @@ -72,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; } } @@ -267,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; } } @@ -297,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 24b482ac597d25f43915c55d7b112de4fec3f92f..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,10 +30,9 @@ #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), _free_slots_list(name, &_segmented_array) { @@ -41,26 +40,38 @@ G1CardSetAllocator::G1CardSetAllocator(const char* name, 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 -void G1CardSetAllocator::free(Slot* slot) { +void G1CardSetAllocator::free(void* slot) { assert(slot != nullptr, "precondition"); - slot->~Slot(); _free_slots_list.release(slot); } -template -void G1CardSetAllocator::drop_all() { +void G1CardSetAllocator::drop_all() { _free_slots_list.reset(); _segmented_array.drop_all(); } -template -void G1CardSetAllocator::print(outputStream* os) { +size_t G1CardSetAllocator::mem_size() const { + return sizeof(*this) + + _segmented_array.num_segments() * sizeof(G1CardSetSegment) + + _segmented_array.num_available_slots() * _segmented_array.slot_size(); +} + +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(); +} + +uint G1CardSetAllocator::num_segments() const { + return _segmented_array.num_segments(); +} + +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 @@ -82,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)); } } @@ -106,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() { @@ -127,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 c455706a616ff0b030a4379619e984e0a4ec7b81..4b5638c33636ddcd4c0c342c5ffa6932efaf54c7 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 @@ -50,7 +50,7 @@ public: static const uint SlotAlignment = 8; G1CardSetAllocOptions(uint slot_size, uint initial_num_slots = MinimumNumSlots, uint max_num_slots = MaximumNumSlots) : - G1SegmentedArrayAllocOptions(align_up(slot_size, SlotAlignment), initial_num_slots, max_num_slots, SlotAlignment) { + G1SegmentedArrayAllocOptions(mtGCCardSet, slot_size, initial_num_slots, max_num_slots, SlotAlignment) { } virtual uint next_num_slots(uint prev_num_slots) const override { @@ -58,41 +58,16 @@ public: } }; -typedef G1SegmentedArraySegment G1CardSetSegment; +using G1CardSetSegment = G1SegmentedArraySegment; -typedef G1SegmentedArrayFreeList G1CardSetFreeList; +using G1CardSetFreeList = G1SegmentedArrayFreeList; -// 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. - - SegmentedArray _segmented_array; + G1SegmentedArray _segmented_array; FreeListAllocator _free_slots_list; public: @@ -101,37 +76,28 @@ 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 { - 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(); - } + size_t wasted_mem_size() const; - inline uint num_segments() { return _segmented_array.num_segments(); } + uint num_segments() const; void print(outputStream* os); }; -typedef G1SegmentedArrayFreePool G1CardSetFreePool; +using G1CardSetFreePool = G1SegmentedArrayFreePool; 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 7d75f86bb7dfe6f679ad4498c16d5c53966604a4..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,16 +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 -Slot* G1CardSetAllocator::allocate() { - Slot* slot = ::new (_free_slots_list.allocate()) Slot(); +inline void* G1CardSetAllocator::allocate() { + void* slot = _free_slots_list.allocate(); assert(slot != nullptr, "must be"); return slot; } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index cbd13a7f282e8096c44bd2de818c17a183ef1cde..a2c6c226b028767e5fc29f2387bd9d3dde0d3575 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2279,7 +2279,7 @@ void G1CollectedHeap::object_iterate_parallel(ObjectClosure* cl, uint worker_id, } void G1CollectedHeap::keep_alive(oop obj) { - G1BarrierSet::enqueue(obj); + G1BarrierSet::enqueue_preloaded(obj); } void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { @@ -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 1fad936447d9f0d2d923d8b28e31f2f45daf22f3..de2442c7ce57588fa70feccb6129180b7bd3bd2e 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1179,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) { @@ -1249,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 af778e43b13798a425260601001ada7d733ef7a0..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 a67fb06a333d68d8774686c82e3742ccf9e188e2..d521c98b39051e0be112a3d02b561572f644b6e4 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/gc/g1/g1EvacFailureRegions.hpp b/src/hotspot/share/gc/g1/g1EvacFailureRegions.hpp index b524ffaa58f562a752e25910235007ab80fec88b..9561a3b89b514b239e9c96a2488e1c545caadf58 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureRegions.hpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureRegions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp b/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp index cf5abb0176f1b8ebe0b068acf9e4932c260d9558..aad6c3170b033e176958f18c9bfb507a910d220d 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index 256fd766f82cf852efe477bbfae2cc2b50165044..ce3013138cef1aecb69b70b787fc9d9a3f1dab7c 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -138,7 +138,7 @@ inline void G1FullGCMarker::follow_object(oop obj) { } else { obj->oop_iterate(mark_closure()); if (VerifyDuringGC) { - if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_reference_instance_klass()) { + if (obj->is_instanceRef()) { return; } _verify_closure.set_containing_obj(obj); diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.cpp b/src/hotspot/share/gc/g1/g1SegmentedArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a77fab8a2125844951718d2195b360a24053cd3 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.cpp @@ -0,0 +1,246 @@ +/* + * 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/g1/g1SegmentedArray.inline.hpp" +#include "memory/allocation.hpp" +#include "runtime/atomic.hpp" +#include "utilities/globalCounter.inline.hpp" + +G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS flag) : + _slot_size(slot_size), + _num_slots(num_slots), + _mem_flag(flag), + _next(next), + _next_allocate(0) { + _bottom = ((char*) this) + header_size(); +} + +G1SegmentedArraySegment* G1SegmentedArraySegment::create_segment(uint slot_size, + uint num_slots, + G1SegmentedArraySegment* next, + MEMFLAGS mem_flag) { + size_t block_size = size_in_bytes(slot_size, num_slots); + char* alloc_block = NEW_C_HEAP_ARRAY(char, block_size, mem_flag); + return new (alloc_block) G1SegmentedArraySegment(slot_size, num_slots, next, mem_flag); +} + +void G1SegmentedArraySegment::delete_segment(G1SegmentedArraySegment* segment) { + segment->~G1SegmentedArraySegment(); + FREE_C_HEAP_ARRAY(_mem_flag, segment); +} + +void G1SegmentedArrayFreeList::bulk_add(G1SegmentedArraySegment& first, + G1SegmentedArraySegment& last, + size_t num, + size_t mem_size) { + _list.prepend(first, last); + Atomic::add(&_num_segments, num, memory_order_relaxed); + Atomic::add(&_mem_size, mem_size, memory_order_relaxed); +} + +void G1SegmentedArrayFreeList::print_on(outputStream* out, const char* prefix) { + out->print_cr("%s: segments %zu size %zu", + prefix, Atomic::load(&_num_segments), Atomic::load(&_mem_size)); +} + +G1SegmentedArraySegment* G1SegmentedArrayFreeList::get_all(size_t& num_segments, + size_t& mem_size) { + GlobalCounter::CriticalSection cs(Thread::current()); + + G1SegmentedArraySegment* result = _list.pop_all(); + num_segments = Atomic::load(&_num_segments); + mem_size = Atomic::load(&_mem_size); + + if (result != nullptr) { + Atomic::sub(&_num_segments, num_segments, memory_order_relaxed); + Atomic::sub(&_mem_size, mem_size, memory_order_relaxed); + } + return result; +} + +void G1SegmentedArrayFreeList::free_all() { + size_t num_freed = 0; + size_t mem_size_freed = 0; + G1SegmentedArraySegment* cur; + + while ((cur = _list.pop()) != nullptr) { + mem_size_freed += cur->mem_size(); + num_freed++; + G1SegmentedArraySegment::delete_segment(cur); + } + + Atomic::sub(&_num_segments, num_freed, memory_order_relaxed); + Atomic::sub(&_mem_size, mem_size_freed, memory_order_relaxed); +} + +G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) { + // Take an existing segment if available. + G1SegmentedArraySegment* next = _free_segment_list->get(); + if (next == nullptr) { + uint prev_num_slots = (prev != nullptr) ? prev->num_slots() : 0; + uint num_slots = _alloc_options->next_num_slots(prev_num_slots); + + next = G1SegmentedArraySegment::create_segment(slot_size(), num_slots, prev, _alloc_options->mem_flag()); + } else { + assert(slot_size() == next->slot_size() , + "Mismatch %d != %d", slot_size(), next->slot_size()); + next->reset(prev); + } + + // Install it as current allocation segment. + G1SegmentedArraySegment* old = Atomic::cmpxchg(&_first, prev, next); + if (old != prev) { + // Somebody else installed the segment, use that one. + G1SegmentedArraySegment::delete_segment(next); + return old; + } else { + // Did we install the first segment in the list? If so, this is also the last. + if (prev == nullptr) { + _last = next; + } + // Successfully installed the segment into the list. + Atomic::inc(&_num_segments, memory_order_relaxed); + Atomic::add(&_mem_size, next->mem_size(), memory_order_relaxed); + Atomic::add(&_num_available_slots, next->num_slots(), memory_order_relaxed); + return next; + } +} + +G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, + G1SegmentedArrayFreeList* free_segment_list) : + _alloc_options(alloc_options), + _first(nullptr), + _last(nullptr), + _num_segments(0), + _mem_size(0), + _free_segment_list(free_segment_list), + _num_available_slots(0), + _num_allocated_slots(0) { + assert(_free_segment_list != nullptr, "precondition!"); +} + +G1SegmentedArray::~G1SegmentedArray() { + drop_all(); +} + +uint G1SegmentedArray::slot_size() const { + return _alloc_options->slot_size(); +} + +void G1SegmentedArray::drop_all() { + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); + + if (cur != nullptr) { + assert(_last != nullptr, "If there is at least one segment, there must be a last one."); + + G1SegmentedArraySegment* first = cur; +#ifdef ASSERT + // Check list consistency. + G1SegmentedArraySegment* last = cur; + uint num_segments = 0; + size_t mem_size = 0; + while (cur != nullptr) { + mem_size += cur->mem_size(); + num_segments++; + + G1SegmentedArraySegment* next = cur->next(); + last = cur; + cur = next; + } +#endif + assert(num_segments == _num_segments, "Segment count inconsistent %u %u", num_segments, _num_segments); + assert(mem_size == _mem_size, "Memory size inconsistent"); + assert(last == _last, "Inconsistent last segment"); + + _free_segment_list->bulk_add(*first, *_last, _num_segments, _mem_size); + } + + _first = nullptr; + _last = nullptr; + _num_segments = 0; + _mem_size = 0; + _num_available_slots = 0; + _num_allocated_slots = 0; +} + +void* G1SegmentedArray::allocate() { + assert(slot_size() > 0, "instance size not set."); + + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); + if (cur == nullptr) { + cur = create_new_segment(cur); + } + + while (true) { + 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()), + "result " PTR_FORMAT " not aligned at %u", p2i(slot), _alloc_options->slot_alignment()); + return slot; + } + // The segment is full. Next round. + assert(cur->is_full(), "must be"); + cur = create_new_segment(cur); + } +} + +uint G1SegmentedArray::num_segments() const { + return Atomic::load(&_num_segments); +} + +#ifdef ASSERT +class LengthClosure { + uint _total; +public: + LengthClosure() : _total(0) {} + void do_segment(G1SegmentedArraySegment* segment, uint limit) { + _total += limit; + } + uint length() const { + return _total; + } +}; + +uint G1SegmentedArray::calculate_length() const { + LengthClosure closure; + iterate_segments(closure); + return closure.length(); +} +#endif + +template +void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const { + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); + + assert((cur != nullptr) == (_last != nullptr), + "If there is at least one segment, there must be a last one"); + + while (cur != nullptr) { + closure.do_segment(cur, cur->length()); + cur = cur->next(); + } +} diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp index bddb6af15fe99089a7bbabf4e13c7c16cc20bc7b..1849a9689fcdae1b988fc861c353f2f43cdf4f6e 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,28 +28,38 @@ #include "gc/shared/freeListAllocator.hpp" #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/lockFreeStack.hpp" // A single segment/arena containing _num_slots blocks of memory of _slot_size. // G1SegmentedArraySegments can be linked together using a singly linked list. -template -class G1SegmentedArraySegment : public CHeapObj { +class G1SegmentedArraySegment { const uint _slot_size; const uint _num_slots; - + const MEMFLAGS _mem_flag; G1SegmentedArraySegment* volatile _next; - - char* _segment; // Actual data. - // Index into the next free slot to allocate into. Full if equal (or larger) // to _num_slots (can be larger because we atomically increment this value and // check only afterwards if the allocation has been successful). uint volatile _next_allocate; -public: - G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next); - ~G1SegmentedArraySegment(); + char* _bottom; // Actual data. + // Do not add class member variables beyond this point + + static size_t header_size() { return align_up(offset_of(G1SegmentedArraySegment, _bottom), DEFAULT_CACHE_LINE_SIZE); } + + static size_t payload_size(uint slot_size, uint num_slots) { + // The cast (size_t) is required to guard against overflow wrap around. + return (size_t)slot_size * num_slots; + } + + size_t payload_size() const { return payload_size(_slot_size, _num_slots); } + NONCOPYABLE(G1SegmentedArraySegment); + + G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS flag); + ~G1SegmentedArraySegment() = default; +public: G1SegmentedArraySegment* volatile* next_addr() { return &_next; } void* get_new_slot(); @@ -67,12 +77,12 @@ public: _next_allocate = 0; assert(next != this, " loop condition"); set_next(next); - memset((void*)_segment, 0, (size_t)_num_slots * _slot_size); + memset((void*)_bottom, 0, payload_size()); } uint slot_size() const { return _slot_size; } - size_t mem_size() const { return sizeof(*this) + (size_t)_num_slots * _slot_size; } + size_t mem_size() const { return header_size() + payload_size(); } uint length() const { // _next_allocate might grow larger than _num_slots in multi-thread environments @@ -80,9 +90,16 @@ public: return MIN2(_next_allocate, _num_slots); } + static size_t size_in_bytes(uint slot_size, uint num_slots) { + return header_size() + payload_size(slot_size, num_slots); + } + + static G1SegmentedArraySegment* create_segment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS mem_flag); + static void delete_segment(G1SegmentedArraySegment* segment); + // Copies the (valid) contents of this segment into the destination. void copy_to(void* dest) const { - ::memcpy(dest, _segment, length() * _slot_size); + ::memcpy(dest, _bottom, length() * _slot_size); } bool is_full() const { return _next_allocate >= _num_slots; } @@ -92,12 +109,11 @@ public: // to it and removal of segments is strictly separate, but every action may be // performed by multiple threads at the same time. // Counts and memory usage are current on a best-effort basis if accessed concurrently. -template class G1SegmentedArrayFreeList { - static G1SegmentedArraySegment* volatile* next_ptr(G1SegmentedArraySegment& segment) { + static G1SegmentedArraySegment* volatile* next_ptr(G1SegmentedArraySegment& segment) { return segment.next_addr(); } - typedef LockFreeStack, &G1SegmentedArrayFreeList::next_ptr> SegmentStack; + using SegmentStack = LockFreeStack; SegmentStack _list; @@ -108,10 +124,10 @@ public: G1SegmentedArrayFreeList() : _list(), _num_segments(0), _mem_size(0) { } ~G1SegmentedArrayFreeList() { free_all(); } - void bulk_add(G1SegmentedArraySegment& first, G1SegmentedArraySegment& last, size_t num, size_t mem_size); + void bulk_add(G1SegmentedArraySegment& first, G1SegmentedArraySegment& last, size_t num, size_t mem_size); - G1SegmentedArraySegment* get(); - G1SegmentedArraySegment* get_all(size_t& num_segments, size_t& mem_size); + G1SegmentedArraySegment* get(); + G1SegmentedArraySegment* get_all(size_t& num_segments, size_t& mem_size); // Give back all memory to the OS. void free_all(); @@ -126,6 +142,7 @@ public: class G1SegmentedArrayAllocOptions { protected: + const MEMFLAGS _mem_flag; const uint _slot_size; const uint _initial_num_slots; // Defines a limit to the number of slots in the segment @@ -133,8 +150,9 @@ protected: const uint _slot_alignment; public: - G1SegmentedArrayAllocOptions(uint slot_size, uint initial_num_slots, uint max_num_slots, uint alignment) : - _slot_size(slot_size), + G1SegmentedArrayAllocOptions(MEMFLAGS mem_flag, uint slot_size, uint initial_num_slots, uint max_num_slots, uint alignment) : + _mem_flag(mem_flag), + _slot_size(align_up(slot_size, alignment)), _initial_num_slots(initial_num_slots), _max_num_slots(max_num_slots), _slot_alignment(alignment) { @@ -151,6 +169,8 @@ public: uint slot_size() const { return _slot_size; } uint slot_alignment() const { return _slot_alignment; } + + MEMFLAGS mem_flag() const {return _mem_flag; } }; // A segmented array where G1SegmentedArraySegment is the segment, and @@ -181,30 +201,30 @@ 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 : public FreeListConfig { // G1SegmentedArrayAllocOptions provides parameters for allocation segment // sizing and expansion. const G1SegmentedArrayAllocOptions* _alloc_options; - G1SegmentedArraySegment* volatile _first; // The (start of the) list of all segments. - G1SegmentedArraySegment* _last; // The last segment of the list of all segments. - volatile uint _num_segments; // Number of assigned segments to this allocator. - volatile size_t _mem_size; // Memory used by all segments. + G1SegmentedArraySegment* volatile _first; // The (start of the) list of all segments. + G1SegmentedArraySegment* _last; // The last segment of the list of all segments. + volatile uint _num_segments; // Number of assigned segments to this allocator. + volatile size_t _mem_size; // Memory used by all segments. - G1SegmentedArrayFreeList* _free_segment_list; // The global free segment list to - // preferentially get new segments from. + G1SegmentedArrayFreeList* _free_segment_list; // The global free segment list to preferentially + // get new segments from. volatile uint _num_available_slots; // Number of slots available in all segments (allocated + free + pending + not yet used). volatile uint _num_allocated_slots; // Number of total slots allocated and in use. private: - inline G1SegmentedArraySegment* create_new_segment(G1SegmentedArraySegment* const prev); + inline G1SegmentedArraySegment* create_new_segment(G1SegmentedArraySegment* const prev); DEBUG_ONLY(uint calculate_length() const;) public: - const G1SegmentedArraySegment* first_array_segment() const { return Atomic::load(&_first); } + const G1SegmentedArraySegment* first_array_segment() const { return Atomic::load(&_first); } uint num_available_slots() const { return Atomic::load(&_num_available_slots); } uint num_allocated_slots() const { @@ -213,10 +233,10 @@ public: return allocated; } - inline uint slot_size() const; + uint slot_size() const; G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, - G1SegmentedArrayFreeList* free_segment_list); + G1SegmentedArrayFreeList* free_segment_list); ~G1SegmentedArray(); // Deallocate all segments to the free segment list and reset this allocator. Must @@ -228,7 +248,7 @@ public: // We do not deallocate individual slots inline void deallocate(void* node) override { ShouldNotReachHere(); } - inline uint num_segments() const; + uint num_segments() const; template void iterate_segments(SegmentClosure& closure) const; diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp index 51b778d82f03f27283b75db347863556aa13f8b6..3aa8a98b75f51029798ccb9b4d44f50f1d019aaa 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,20 +30,7 @@ #include "runtime/atomic.hpp" #include "utilities/globalCounter.inline.hpp" -template -G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next) : - _slot_size(slot_size), _num_slots(num_slots), _next(next), _next_allocate(0) { - - _segment = NEW_C_HEAP_ARRAY(char, (size_t)_num_slots * slot_size, flag); -} - -template -G1SegmentedArraySegment::~G1SegmentedArraySegment() { - FREE_C_HEAP_ARRAY(flag, _segment); -} - -template -void* G1SegmentedArraySegment::get_new_slot() { +inline void* G1SegmentedArraySegment::get_new_slot() { if (_next_allocate >= _num_slots) { return nullptr; } @@ -51,31 +38,14 @@ void* G1SegmentedArraySegment::get_new_slot() { if (result >= _num_slots) { return nullptr; } - void* r = _segment + (uint)result * _slot_size; + void* r = _bottom + (size_t)result * _slot_size; return r; } -template -void G1SegmentedArrayFreeList::bulk_add(G1SegmentedArraySegment& first, - G1SegmentedArraySegment& last, - size_t num, - size_t mem_size) { - _list.prepend(first, last); - Atomic::add(&_num_segments, num, memory_order_relaxed); - Atomic::add(&_mem_size, mem_size, memory_order_relaxed); -} - -template -void G1SegmentedArrayFreeList::print_on(outputStream* out, const char* prefix) { - out->print_cr("%s: segments %zu size %zu", - prefix, Atomic::load(&_num_segments), Atomic::load(&_mem_size)); -} - -template -G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() { +inline G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() { GlobalCounter::CriticalSection cs(Thread::current()); - G1SegmentedArraySegment* result = _list.pop(); + G1SegmentedArraySegment* result = _list.pop(); if (result != nullptr) { Atomic::dec(&_num_segments, memory_order_relaxed); Atomic::sub(&_mem_size, result->mem_size(), memory_order_relaxed); @@ -83,194 +53,4 @@ G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() { return result; } -template -G1SegmentedArraySegment* G1SegmentedArrayFreeList::get_all(size_t& num_segments, - size_t& mem_size) { - GlobalCounter::CriticalSection cs(Thread::current()); - - G1SegmentedArraySegment* result = _list.pop_all(); - num_segments = Atomic::load(&_num_segments); - mem_size = Atomic::load(&_mem_size); - - if (result != nullptr) { - Atomic::sub(&_num_segments, num_segments, memory_order_relaxed); - Atomic::sub(&_mem_size, mem_size, memory_order_relaxed); - } - return result; -} - -template -void G1SegmentedArrayFreeList::free_all() { - size_t num_freed = 0; - size_t mem_size_freed = 0; - G1SegmentedArraySegment* cur; - - while ((cur = _list.pop()) != nullptr) { - mem_size_freed += cur->mem_size(); - num_freed++; - delete cur; - } - - Atomic::sub(&_num_segments, num_freed, memory_order_relaxed); - Atomic::sub(&_mem_size, mem_size_freed, memory_order_relaxed); -} - -template -G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) { - // Take an existing segment if available. - G1SegmentedArraySegment* next = _free_segment_list->get(); - if (next == nullptr) { - uint prev_num_slots = (prev != nullptr) ? prev->num_slots() : 0; - uint num_slots = _alloc_options->next_num_slots(prev_num_slots); - 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)); - next->reset(prev); - } - - // Install it as current allocation segment. - G1SegmentedArraySegment* old = Atomic::cmpxchg(&_first, prev, next); - if (old != prev) { - // Somebody else installed the segment, use that one. - delete next; - return old; - } else { - // Did we install the first segment in the list? If so, this is also the last. - if (prev == nullptr) { - _last = next; - } - // Successfully installed the segment into the list. - Atomic::inc(&_num_segments, memory_order_relaxed); - Atomic::add(&_mem_size, next->mem_size(), memory_order_relaxed); - Atomic::add(&_num_available_slots, next->num_slots(), memory_order_relaxed); - return next; - } -} - -template -uint G1SegmentedArray::slot_size() const { - return _alloc_options->slot_size(); -} - -template -G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, - G1SegmentedArrayFreeList* free_segment_list) : - _alloc_options(alloc_options), - _first(nullptr), - _last(nullptr), - _num_segments(0), - _mem_size(0), - _free_segment_list(free_segment_list), - _num_available_slots(0), - _num_allocated_slots(0) { - assert(_free_segment_list != nullptr, "precondition!"); -} - -template -G1SegmentedArray::~G1SegmentedArray() { - drop_all(); -} - -template -void G1SegmentedArray::drop_all() { - G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); - - if (cur != nullptr) { - assert(_last != nullptr, "If there is at least one segment, there must be a last one."); - - G1SegmentedArraySegment* first = cur; -#ifdef ASSERT - // Check list consistency. - G1SegmentedArraySegment* last = cur; - uint num_segments = 0; - size_t mem_size = 0; - while (cur != nullptr) { - mem_size += cur->mem_size(); - num_segments++; - - G1SegmentedArraySegment* next = cur->next(); - last = cur; - cur = next; - } -#endif - assert(num_segments == _num_segments, "Segment count inconsistent %u %u", num_segments, _num_segments); - assert(mem_size == _mem_size, "Memory size inconsistent"); - assert(last == _last, "Inconsistent last segment"); - - _free_segment_list->bulk_add(*first, *_last, _num_segments, _mem_size); - } - - _first = nullptr; - _last = nullptr; - _num_segments = 0; - _mem_size = 0; - _num_available_slots = 0; - _num_allocated_slots = 0; -} - -template -void* G1SegmentedArray::allocate() { - assert(slot_size() > 0, "instance size not set."); - - G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); - if (cur == nullptr) { - cur = create_new_segment(cur); - } - - while (true) { - Slot* slot = (Slot*)cur->get_new_slot(); - if (slot != nullptr) { - Atomic::inc(&_num_allocated_slots, memory_order_relaxed); - guarantee(is_aligned(slot, _alloc_options->slot_alignment()), - "result " PTR_FORMAT " not aligned at %u", p2i(slot), _alloc_options->slot_alignment()); - return slot; - } - // The segment is full. Next round. - assert(cur->is_full(), "must be"); - cur = create_new_segment(cur); - } -} - -template -inline uint G1SegmentedArray::num_segments() const { - return Atomic::load(&_num_segments); -} - -#ifdef ASSERT -template -class LengthClosure { - uint _total; -public: - LengthClosure() : _total(0) {} - void do_segment(G1SegmentedArraySegment* segment, uint limit) { - _total += limit; - } - uint length() const { - return _total; - } -}; - -template -uint G1SegmentedArray::calculate_length() const { - LengthClosure closure; - iterate_segments(closure); - return closure.length(); -} -#endif - -template -template -void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const { - G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); - - assert((cur != nullptr) == (_last != nullptr), - "If there is at least one segment, there must be a last one"); - - while (cur != nullptr) { - closure.do_segment(cur, cur->length()); - cur = cur->next(); - } -} - #endif //SHARE_GC_G1_G1SEGMENTEDARRAY_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp index 4752adde74d2d3be284b9c951f64033b0d45dbb4..5bef0caca0b706248a62e31be9a1c6527ab684b6 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.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 @@ -52,7 +52,7 @@ bool G1SegmentedArrayFreeMemoryTask::calculate_return_infos(jlong deadline) { // Ignore the deadline in this step as it is very short. G1SegmentedArrayMemoryStats used = _total_used; - G1SegmentedArrayMemoryStats free = G1SegmentedArrayFreePool::free_list_sizes(); + G1SegmentedArrayMemoryStats free = G1SegmentedArrayFreePool::free_list_sizes(); _return_info = new G1ReturnMemoryProcessorSet(used.num_pools()); for (uint i = 0; i < used.num_pools(); i++) { @@ -68,7 +68,7 @@ bool G1SegmentedArrayFreeMemoryTask::calculate_return_infos(jlong deadline) { _return_info->append(new G1ReturnMemoryProcessor(return_to_vm_size)); } - G1SegmentedArrayFreePool::update_unlink_processors(_return_info); + G1SegmentedArrayFreePool::update_unlink_processors(_return_info); return false; } diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp index a4195cd424c669ef414237868b4a644313de9190..487f553ea7b1db8efda60a4a39d1b7d0fc73cb8a 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.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 @@ -56,8 +56,8 @@ class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask { // Current total segmented array memory usage. G1SegmentedArrayMemoryStats _total_used; - typedef G1SegmentedArrayFreePool::G1ReturnMemoryProcessor G1ReturnMemoryProcessor; - typedef G1SegmentedArrayFreePool::G1ReturnMemoryProcessorSet G1ReturnMemoryProcessorSet; + using G1ReturnMemoryProcessor = G1SegmentedArrayFreePool::G1ReturnMemoryProcessor; + using G1ReturnMemoryProcessorSet = G1SegmentedArrayFreePool::G1ReturnMemoryProcessorSet; G1ReturnMemoryProcessorSet* _return_info; diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp index 118638da75bee9887a455926039223e41b7c67a5..10f69405569b837c4276edda9a0e4c88af40c5d3 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.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 @@ -43,8 +43,7 @@ void G1SegmentedArrayMemoryStats::clear() { } } -template -void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { +void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { uint num_free_lists = _freelist_pool.num_free_lists(); for (uint i = 0; i < num_free_lists; i++) { @@ -52,8 +51,7 @@ void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProc } } -template -void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1SegmentedArrayFreeList* source) { +void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1SegmentedArrayFreeList* source) { assert(_source == nullptr, "already visited"); if (_return_to_vm_size > 0) { _source = source; @@ -75,16 +73,15 @@ void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1 } } -template -bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { +bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { assert(!finished_return_to_vm(), "already returned everything to the VM"); assert(_first != nullptr, "must have segment to return"); size_t keep_size = 0; size_t keep_num = 0; - G1SegmentedArraySegment* cur = _first; - G1SegmentedArraySegment* last = nullptr; + G1SegmentedArraySegment* cur = _first; + G1SegmentedArraySegment* last = nullptr; while (cur != nullptr && _return_to_vm_size > 0) { size_t cur_size = cur->mem_size(); @@ -125,8 +122,7 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong return _source != nullptr; } -template -bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { +bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { assert(finished_return_to_vm(), "not finished returning to VM"); assert(!finished_return_to_os(), "already returned everything to the OS"); @@ -135,10 +131,10 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong size_t mem_size_deleted = 0; while (_first != nullptr) { - G1SegmentedArraySegment* next = _first->next(); + G1SegmentedArraySegment* next = _first->next(); num_delete++; mem_size_deleted += _first->mem_size(); - delete _first; + G1SegmentedArraySegment::delete_segment(_first); _first = next; // To ensure progress, perform the deadline check here. @@ -152,29 +148,25 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong return _first != nullptr; } -template -G1SegmentedArrayFreePool G1SegmentedArrayFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); +G1SegmentedArrayFreePool G1SegmentedArrayFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); -template -G1SegmentedArrayFreePool::G1SegmentedArrayFreePool(uint num_free_lists) : +G1SegmentedArrayFreePool::G1SegmentedArrayFreePool(uint num_free_lists) : _num_free_lists(num_free_lists) { - _free_lists = NEW_C_HEAP_ARRAY(G1SegmentedArrayFreeList < flag >, _num_free_lists, mtGC); + _free_lists = NEW_C_HEAP_ARRAY(G1SegmentedArrayFreeList, _num_free_lists, mtGC); for (uint i = 0; i < _num_free_lists; i++) { - new (&_free_lists[i]) G1SegmentedArrayFreeList(); + new (&_free_lists[i]) G1SegmentedArrayFreeList(); } } -template -G1SegmentedArrayFreePool::~G1SegmentedArrayFreePool() { +G1SegmentedArrayFreePool::~G1SegmentedArrayFreePool() { for (uint i = 0; i < _num_free_lists; i++) { - _free_lists[i].~G1SegmentedArrayFreeList(); + _free_lists[i].~G1SegmentedArrayFreeList(); } FREE_C_HEAP_ARRAY(mtGC, _free_lists); } -template -G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const { +G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const { G1SegmentedArrayMemoryStats free_list_stats; assert(free_list_stats.num_pools() == num_free_lists(), "must be"); for (uint i = 0; i < num_free_lists(); i++) { @@ -184,8 +176,7 @@ G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const return free_list_stats; } -template -size_t G1SegmentedArrayFreePool::mem_size() const { +size_t G1SegmentedArrayFreePool::mem_size() const { size_t result = 0; for (uint i = 0; i < _num_free_lists; i++) { result += _free_lists[i].mem_size(); @@ -193,13 +184,10 @@ size_t G1SegmentedArrayFreePool::mem_size() const { return result; } -template -void G1SegmentedArrayFreePool::print_on(outputStream* out) { +void G1SegmentedArrayFreePool::print_on(outputStream* out) { out->print_cr(" Free Pool: size %zu", free_list_pool()->mem_size()); for (uint i = 0; i < _num_free_lists; i++) { FormatBuffer<> fmt(" %s", G1CardSetConfiguration::mem_object_type_name_str(i)); _free_lists[i].print_on(out, fmt); } } - -template class G1SegmentedArrayFreePool; diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp index ba1b952875c5f3c6470c8c338570f29ffc1262d1..23079c3853fd98cb052791a39a692ba72961dc53 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.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 @@ -56,13 +56,12 @@ public: // A set of free lists holding freed segments for use by G1SegmentedArray, // e.g. G1CardSetAllocators::SegmentedArray -template class G1SegmentedArrayFreePool { // The global free pool. static G1SegmentedArrayFreePool _freelist_pool; const uint _num_free_lists; - G1SegmentedArrayFreeList* _free_lists; + G1SegmentedArrayFreeList* _free_lists; public: static G1SegmentedArrayFreePool* free_list_pool() { return &_freelist_pool; } @@ -76,7 +75,7 @@ public: explicit G1SegmentedArrayFreePool(uint num_free_lists); ~G1SegmentedArrayFreePool(); - G1SegmentedArrayFreeList* free_list(uint i) { + G1SegmentedArrayFreeList* free_list(uint i) { assert(i < _num_free_lists, "must be"); return &_free_lists[i]; } @@ -91,12 +90,11 @@ public: // Data structure containing current in-progress state for returning memory to the // operating system for a single G1SegmentedArrayFreeList. -template -class G1SegmentedArrayFreePool::G1ReturnMemoryProcessor : public CHeapObj { - G1SegmentedArrayFreeList* _source; +class G1SegmentedArrayFreePool::G1ReturnMemoryProcessor : public CHeapObj { + G1SegmentedArrayFreeList* _source; size_t _return_to_vm_size; - G1SegmentedArraySegment* _first; + G1SegmentedArraySegment* _first; size_t _unlinked_bytes; size_t _num_unlinked; @@ -108,7 +106,7 @@ public: // Updates the instance members about the given free list for // the purpose of giving back memory. Only necessary members are updated, // e.g. if there is nothing to return to the VM, do not set the source list. - void visit_free_list(G1SegmentedArrayFreeList* source); + void visit_free_list(G1SegmentedArrayFreeList* source); bool finished_return_to_vm() const { return _return_to_vm_size == 0; } bool finished_return_to_os() const { return _first == 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.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index 9e6c31ffdc11aa55a49b52de10325ce9c2b4c38f..9b661768ae1b8a03c493f16a7afd63b464ab8e65 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.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 @@ -81,7 +81,7 @@ HeapRegionRemSet::HeapRegionRemSet(HeapRegion* hr, G1CardSetConfiguration* config) : _m(Mutex::service - 1, FormatBuffer<128>("HeapRegionRemSet#%u_lock", hr->hrm_index())), _code_roots(), - _card_set_mm(config, G1SegmentedArrayFreePool::free_list_pool()), + _card_set_mm(config, G1SegmentedArrayFreePool::free_list_pool()), _card_set(config, &_card_set_mm), _hr(hr), _state(Untracked) { } 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/parallelInitLogger.hpp b/src/hotspot/share/gc/parallel/parallelInitLogger.hpp index ecd9b453f1f7a101229610cbab242f6e6d83f31c..2a3b6349964d6a58da67a7287350a1871078f7eb 100644 --- a/src/hotspot/share/gc/parallel/parallelInitLogger.hpp +++ b/src/hotspot/share/gc/parallel/parallelInitLogger.hpp @@ -34,4 +34,4 @@ class ParallelInitLogger : public GCInitLogger { static void print(); }; -#endif //SHARE_GC_PARALLEL_PARALLELINITLOGGER_HPP \ No newline at end of file +#endif //SHARE_GC_PARALLEL_PARALLELINITLOGGER_HPP diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index cda8d7446cad0f10fc6e65d0a6206e42728508c0..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(); } 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/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/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.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index b6ca29adefcae194895d2b08217fb7f4a4056ac8..049bacaf1a574869790d26bb0f37549a0bb2fb00 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -162,13 +162,15 @@ public: } template void do_oop_work(T* p) { - assert (oopDesc::is_oop(RawAccess::oop_load(p)), - "expected an oop while scanning weak refs"); +#ifdef ASSERT + // Referent must be non-null and in from-space + oop obj = RawAccess::oop_load(p); + assert(oopDesc::is_oop(obj), "referent must be an oop"); + assert(PSScavenge::is_obj_in_young(obj), "must be in young-gen"); + assert(!PSScavenge::is_obj_in_to_space(obj), "must be in from-space"); +#endif - // Weak refs may be visited more than once. - if (PSScavenge::should_scavenge(p, _to_space)) { - _promotion_manager->copy_and_push_safe_barrier(p); - } + _promotion_manager->copy_and_push_safe_barrier(p); } virtual void do_oop(oop* p) { PSKeepAliveClosure::do_oop_work(p); } virtual void do_oop(narrowOop* p) { PSKeepAliveClosure::do_oop_work(p); } @@ -758,7 +760,7 @@ void PSScavenge::initialize() { ParallelGCThreads, // mt processing degree ParallelGCThreads, // mt discovery degree false, // concurrent_discovery - NULL); // header provides liveness info + &_is_alive_closure); // header provides liveness info // Cache the cardtable _card_table = heap->card_table(); 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/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/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/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/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 849b40f3d79e1f337ee942bb5b24c098ecbfb3ca..667808f4efd802c054300269bb17364c68bcc6a5 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -567,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} }, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index c7e0c9b0cd9d707baf76c4ef55cfbc0d7edb3450..7d31ff02e1addc02f27e2cfb1398b08409202a86 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.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 @@ -35,7 +35,7 @@ #include "utilities/defaultStream.hpp" void ShenandoahArguments::initialize() { -#if !(defined AARCH64 || defined AMD64 || defined IA32 || defined PPC64) +#if !(defined AARCH64 || defined AMD64 || defined IA32 || defined PPC64 || defined RISCV64) vm_exit_during_initialization("Shenandoah GC is not supported on this platform."); #endif diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp index 4f2e36a8304ce41c920876aa928e1ae90ed25fe0..705d498399a949cf5be6df69d4be68ee1b5df1e7 100644 --- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp @@ -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 @@ -94,7 +94,7 @@ private: public: LIR_OpZLoadBarrierTest(LIR_Opr opr) : - LIR_Op(), + LIR_Op(lir_zloadbarrier_test, LIR_OprFact::illegalOpr, NULL), _opr(opr) {} virtual void visit(LIR_OpVisitState* state) { 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/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 9b29553665716b08c51c884baee414a3f20532df..4790506bf97202ab142e4baad0829f5715541fc4 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.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 @@ -132,7 +132,7 @@ static void handle_dcmd_result(outputStream* output, const bool startup = DCmd_Source_Internal == source; if (HAS_PENDING_EXCEPTION) { handle_pending_exception(output, startup, PENDING_EXCEPTION); - // Don't clear excption on startup, JVM should fail initialization. + // Don't clear exception on startup, JVM should fail initialization. if (!startup) { CLEAR_PENDING_EXCEPTION; } 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/recorder/service/jfrEventThrottler.hpp b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.hpp index 226a2d4ecd221845256c43d12d4b6dd99d113d67..b3c5618363085aef68aac3e1c78992f299a09f43 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.hpp @@ -54,4 +54,4 @@ class JfrEventThrottler : public JfrAdaptiveSampler { static bool accept(JfrEventId event_id, int64_t timestamp = 0); }; -#endif // SHARE_JFR_RECORDER_SERVICE_JFREVENTTHROTTLER_HPP \ No newline at end of file +#endif // SHARE_JFR_RECORDER_SERVICE_JFREVENTTHROTTLER_HPP diff --git a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp index b2e641269e0cd588930a6298650228fb0ffbbdd0..15ae304672165683b5cc75e86daeadb3b83490f3 100644 --- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp +++ b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -102,7 +102,7 @@ inline T JfrBigEndian::read_unaligned(const address location) { inline bool JfrBigEndian::platform_supports_unaligned_reads(void) { #if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390) return true; -#elif defined(ARM) || defined(AARCH64) +#elif defined(ARM) || defined(AARCH64) || defined(RISCV) return false; #else #warning "Unconfigured platform" diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index f789cd6ac0be77dfb9b1cbd5d5ec6d2220b11ac4..47650406b9814a267d64e95d3f105432c474a4a2 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -118,7 +118,7 @@ void JVMCIEnv::copy_saved_properties() { TempNewSymbol serializeSavedProperties = SymbolTable::new_symbol("serializeSavedProperties"); JavaValue result(T_OBJECT); JavaCallArguments args; - JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::serializePropertiesToByteArray_signature(), &args, THREAD); + JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::void_byte_array_signature(), &args, THREAD); if (HAS_PENDING_EXCEPTION) { JVMCIRuntime::fatal_exception(NULL, "Error calling jdk.vm.ci.services.Services.serializeSavedProperties"); } diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 998f1d1ad4f2115db329ba9adb89db8f46145344..7ed48a79eeb1a9c17ae5d9cbb1a9e3430bfe08f5 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -742,8 +742,8 @@ #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, _has_negatives, address) \ - static_field(StubRoutines::aarch64, _has_negatives_long, address) \ + 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*) diff --git a/src/hotspot/share/logging/logOutput.cpp b/src/hotspot/share/logging/logOutput.cpp index 96b9893fa5866747acf594e096a82fc2712a0cfc..662444eca262b5df323548668c7e8368688df126 100644 --- a/src/hotspot/share/logging/logOutput.cpp +++ b/src/hotspot/share/logging/logOutput.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 @@ -334,6 +334,11 @@ void LogOutput::update_config_string(const size_t on_level[LogLevel::Count]) { assert(n_deviates < deviating_tagsets, "deviating tag set array overflow"); assert(prev_deviates > n_deviates, "number of deviating tag sets must never grow"); + + if (n_deviates == 1 && n_selections == 0) { + // we're done as we couldn't reduce things any further + break; + } } FREE_C_HEAP_ARRAY(LogTagSet*, deviates); FREE_C_HEAP_ARRAY(Selection, selections); diff --git a/src/hotspot/share/memory/iterator.inline.hpp b/src/hotspot/share/memory/iterator.inline.hpp index cc339f2213d1437679901222fef3828e658de1a4..90d705ccab61d91de81d9f4167288e9b5902f4c1 100644 --- a/src/hotspot/share/memory/iterator.inline.hpp +++ b/src/hotspot/share/memory/iterator.inline.hpp @@ -174,7 +174,7 @@ void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) { // It allows for a single call to do a multi-dispatch to an optimized version // of oop_oop_iterate that statically know all these types: // - OopClosureType : static type give at call site -// - Klass* : dynamic to static type through Klass::id() -> table index +// - Klass* : dynamic to static type through Klass::kind() -> table index // - UseCompressedOops : dynamic to static value determined once // // when users call obj->oop_iterate(&cl). @@ -190,7 +190,7 @@ void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) { // used when calling do_oop. // // Klass* : -// A table mapping from *Klass::ID to function is setup. This happens once +// A table mapping from *Klass::Kind to function is setup. This happens once // when the program starts, when the static _table instance is initialized for // the OopOopIterateDispatch specialized with the OopClosureType. // @@ -223,7 +223,7 @@ private: template void set_init_function() { - _function[KlassType::ID] = &init; + _function[KlassType::Kind] = &init; } template @@ -232,20 +232,20 @@ private: // when functions pointers are updated. STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*)); if (UseCompressedOops) { - _function[KlassType::ID] = &oop_oop_iterate; + _function[KlassType::Kind] = &oop_oop_iterate; } else { - _function[KlassType::ID] = &oop_oop_iterate; + _function[KlassType::Kind] = &oop_oop_iterate; } } template void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) { set_resolve_function(); - _function[KlassType::ID](cl, obj, k); + _function[KlassType::Kind](cl, obj, k); } public: - FunctionType _function[KLASS_ID_COUNT]; + FunctionType _function[KLASS_KIND_COUNT]; Table(){ set_init_function(); @@ -261,7 +261,7 @@ private: public: static FunctionType function(Klass* klass) { - return _table._function[klass->id()]; + return _table._function[klass->kind()]; } }; @@ -288,26 +288,26 @@ private: template void set_init_function() { - _function[KlassType::ID] = &init; + _function[KlassType::Kind] = &init; } template void set_resolve_function() { if (UseCompressedOops) { - _function[KlassType::ID] = &oop_oop_iterate_bounded; + _function[KlassType::Kind] = &oop_oop_iterate_bounded; } else { - _function[KlassType::ID] = &oop_oop_iterate_bounded; + _function[KlassType::Kind] = &oop_oop_iterate_bounded; } } template void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) { set_resolve_function(); - _function[KlassType::ID](cl, obj, k, mr); + _function[KlassType::Kind](cl, obj, k, mr); } public: - FunctionType _function[KLASS_ID_COUNT]; + FunctionType _function[KLASS_KIND_COUNT]; Table(){ set_init_function(); @@ -323,7 +323,7 @@ private: public: static FunctionType function(Klass* klass) { - return _table._function[klass->id()]; + return _table._function[klass->kind()]; } }; @@ -350,26 +350,26 @@ private: template void set_init_function() { - _function[KlassType::ID] = &init; + _function[KlassType::Kind] = &init; } template void set_resolve_function() { if (UseCompressedOops) { - _function[KlassType::ID] = &oop_oop_iterate_backwards; + _function[KlassType::Kind] = &oop_oop_iterate_backwards; } else { - _function[KlassType::ID] = &oop_oop_iterate_backwards; + _function[KlassType::Kind] = &oop_oop_iterate_backwards; } } template void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) { set_resolve_function(); - _function[KlassType::ID](cl, obj, k); + _function[KlassType::Kind](cl, obj, k); } public: - FunctionType _function[KLASS_ID_COUNT]; + FunctionType _function[KLASS_KIND_COUNT]; Table(){ set_init_function(); @@ -385,7 +385,7 @@ private: public: static FunctionType function(Klass* klass) { - return _table._function[klass->id()]; + return _table._function[klass->kind()]; } }; diff --git a/src/hotspot/share/memory/memRegion.cpp b/src/hotspot/share/memory/memRegion.cpp index 3c8dfc837ba6420f33b4de2dd2747fae7506a599..ed8adc7df94e836b6d740f459801a2b92c8fe588 100644 --- a/src/hotspot/share/memory/memRegion.cpp +++ b/src/hotspot/share/memory/memRegion.cpp @@ -118,4 +118,4 @@ void MemRegion::destroy_array(MemRegion* array, size_t length) { array[i].~MemRegion(); } FREE_C_HEAP_ARRAY(MemRegion, array); -} \ No newline at end of file +} 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 ca68e601cf46d31e3bf818d1e330c58fafac009f..ef244b66912a68c0ab8cd83f53f811536866a8f6 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -1248,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/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/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index c28ce0323b7f2b4e3e14c05e1b87c9e65c42ffc9..5a276fda3d60ac00d9d9a07c71575d01145822fc 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -83,8 +83,8 @@ Method* ArrayKlass::uncached_lookup_method(const Symbol* name, return super()->uncached_lookup_method(name, signature, OverpassLookupMode::skip, private_mode); } -ArrayKlass::ArrayKlass(Symbol* name, KlassID id) : - Klass(id), +ArrayKlass::ArrayKlass(Symbol* name, KlassKind kind) : + Klass(kind), _dimension(1), _higher_dimension(NULL), _lower_dimension(NULL) { diff --git a/src/hotspot/share/oops/arrayKlass.hpp b/src/hotspot/share/oops/arrayKlass.hpp index bed87db0d2a8f6cec0007bb4f81d92303f442f05..62138ce862df3804c51e08ae1d96a2a87eec3149 100644 --- a/src/hotspot/share/oops/arrayKlass.hpp +++ b/src/hotspot/share/oops/arrayKlass.hpp @@ -45,7 +45,7 @@ class ArrayKlass: public Klass { // Constructors // The constructor with the Symbol argument does the real array // initialization, the other is a dummy - ArrayKlass(Symbol* name, KlassID id); + ArrayKlass(Symbol* name, KlassKind kind); ArrayKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); } public: 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/instanceClassLoaderKlass.hpp b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp index b026185462605c193d62d212077935a6d9ab65d5..559878a1c67868a922df7b515bae5b1115d5597b 100644 --- a/src/hotspot/share/oops/instanceClassLoaderKlass.hpp +++ b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp @@ -40,10 +40,10 @@ class InstanceClassLoaderKlass: public InstanceKlass { friend class VMStructs; friend class InstanceKlass; public: - static const KlassID ID = InstanceClassLoaderKlassID; + static const KlassKind Kind = InstanceClassLoaderKlassKind; private: - InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_class_loader, ID) {} + InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {} public: InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 5545732a1c119c9fe68411b0291d8301eeccbfd7..7e761c07f66e11080ab7d032c6cdb7cac580ee0e 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -442,13 +442,12 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par if (class_name == vmSymbols::java_lang_Class()) { // mirror ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser); - } - else if (is_class_loader(class_name, parser)) { + } else if (is_class_loader(class_name, parser)) { // class loader ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser); } else { // normal - ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_kind_other); + ik = new (loader_data, size, THREAD) InstanceKlass(parser); } } else { // reference @@ -486,8 +485,8 @@ Array* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) { return vtable_indices; } -InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id) : - Klass(id), +InstanceKlass::InstanceKlass(const ClassFileParser& parser, KlassKind kind) : + Klass(kind), _nest_members(NULL), _nest_host(NULL), _permitted_subclasses(NULL), @@ -501,7 +500,6 @@ InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, Klass _init_thread(NULL) { set_vtable_length(parser.vtable_size()); - set_kind(kind); set_access_flags(parser.access_flags()); if (parser.is_hidden()) set_is_hidden(); set_layout_helper(Klass::instance_layout_helper(parser.layout_size(), @@ -2074,6 +2072,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); @@ -3393,6 +3437,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); @@ -3400,7 +3448,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..914652726318adaac4249a688a8274eb54cf39b7 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -133,10 +133,10 @@ class InstanceKlass: public Klass { friend class CompileReplay; public: - static const KlassID ID = InstanceKlassID; + static const KlassKind Kind = InstanceKlassKind; protected: - InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id = ID); + InstanceKlass(const ClassFileParser& parser, KlassKind kind = Kind); public: InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } @@ -229,15 +229,7 @@ class InstanceKlass: public Klass { // _idnum_allocated_count. u1 _init_state; // state of class - // This can be used to quickly discriminate among the four kinds of - // InstanceKlass. This should be an enum (?) - static const unsigned _kind_other = 0; // concrete InstanceKlass - static const unsigned _kind_reference = 1; // InstanceRefKlass - static const unsigned _kind_class_loader = 2; // InstanceClassLoaderKlass - static const unsigned _kind_mirror = 3; // InstanceMirrorKlass - u1 _reference_type; // reference type - u1 _kind; // kind of InstanceKlass enum { _misc_rewritten = 1 << 0, // methods rewritten. @@ -547,6 +539,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 @@ -786,24 +779,8 @@ public: void set_has_resolved_methods() { _access_flags.set_has_resolved_methods(); } -private: - - void set_kind(unsigned kind) { - _kind = (u1)kind; - } - - bool is_kind(unsigned desired) const { - return _kind == (u1)desired; - } public: - - // Other is anything that is not one of the more specialized kinds of InstanceKlass. - bool is_other_instance_klass() const { return is_kind(_kind_other); } - bool is_reference_instance_klass() const { return is_kind(_kind_reference); } - bool is_mirror_instance_klass() const { return is_kind(_kind_mirror); } - bool is_class_loader_instance_klass() const { return is_kind(_kind_class_loader); } - #if INCLUDE_JVMTI void init_previous_versions() { @@ -1277,6 +1254,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/instanceMirrorKlass.hpp b/src/hotspot/share/oops/instanceMirrorKlass.hpp index 154151932f7bbaceea60cc4c8f9185d18906d568..cb1ee2efba49aedcc345995c4a28918056e5767a 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp @@ -45,12 +45,12 @@ class InstanceMirrorKlass: public InstanceKlass { friend class InstanceKlass; public: - static const KlassID ID = InstanceMirrorKlassID; + static const KlassKind Kind = InstanceMirrorKlassKind; private: static int _offset_of_static_fields; - InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_mirror, ID) {} + InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {} public: InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } @@ -60,7 +60,7 @@ class InstanceMirrorKlass: public InstanceKlass { } static const InstanceMirrorKlass* cast(const Klass* k) { - assert(InstanceKlass::cast(k)->is_mirror_instance_klass(), "cast to InstanceMirrorKlass"); + assert(k->is_mirror_instance_klass(), "cast to InstanceMirrorKlass"); return static_cast(k); } diff --git a/src/hotspot/share/oops/instanceRefKlass.cpp b/src/hotspot/share/oops/instanceRefKlass.cpp index aab23761e274be4e79805e0d2cc1f61c933d275d..0b3e5e4e0ec5c0f838f71577817fa1c52fdfd816 100644 --- a/src/hotspot/share/oops/instanceRefKlass.cpp +++ b/src/hotspot/share/oops/instanceRefKlass.cpp @@ -87,7 +87,6 @@ void InstanceRefKlass::oop_verify_on(oop obj, outputStream* st) { oop next = java_lang_ref_Reference::next(obj); if (next != NULL) { guarantee(oopDesc::is_oop(next), "next field should be an oop"); - guarantee(next->is_instance(), "next field should be an instance"); - guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed"); + guarantee(next->is_instanceRef(), "next field verify failed"); } } diff --git a/src/hotspot/share/oops/instanceRefKlass.hpp b/src/hotspot/share/oops/instanceRefKlass.hpp index 16a9bb53c3af88fdc4637c09da111a60c5935ab8..5965e072a22d8feb14a2faf9bb0f4868bd53f9b1 100644 --- a/src/hotspot/share/oops/instanceRefKlass.hpp +++ b/src/hotspot/share/oops/instanceRefKlass.hpp @@ -50,10 +50,10 @@ class ClassFileParser; class InstanceRefKlass: public InstanceKlass { friend class InstanceKlass; public: - static const KlassID ID = InstanceRefKlassID; + static const KlassKind Kind = InstanceRefKlassKind; private: - InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_reference, ID) {} + InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {} public: InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index f431c2425d8758f1cd0111bd6d829330201680d6..856669e44caa42fffd9dd7d40156b01930b38283 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -201,7 +201,7 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word // which zeros out memory - calloc equivalent. // The constructor is also used from CppVtableCloner, // which doesn't zero out the memory before calling the constructor. -Klass::Klass(KlassID id) : _id(id), +Klass::Klass(KlassKind kind) : _kind(kind), _shared_class_path_index(-1) { CDS_ONLY(_shared_class_flags = 0;) CDS_JAVA_HEAP_ONLY(_archived_mirror_index = -1;) diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 9871036d5764b6364ec9d743b8ac891f446d5c29..3d1d98c70373f7b095cb059adb5bf23c40f5ad38 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -37,17 +37,17 @@ #include "jfr/support/jfrTraceIdExtension.hpp" #endif -// Klass IDs for all subclasses of Klass -enum KlassID { - InstanceKlassID, - InstanceRefKlassID, - InstanceMirrorKlassID, - InstanceClassLoaderKlassID, - TypeArrayKlassID, - ObjArrayKlassID +// Klass Kinds for all subclasses of Klass +enum KlassKind { + InstanceKlassKind, + InstanceRefKlassKind, + InstanceMirrorKlassKind, + InstanceClassLoaderKlassKind, + TypeArrayKlassKind, + ObjArrayKlassKind }; -const uint KLASS_ID_COUNT = 6; +const uint KLASS_KIND_COUNT = ObjArrayKlassKind + 1; // // A Klass provides: @@ -114,8 +114,10 @@ class Klass : public Metadata { // because it is frequently queried. jint _layout_helper; - // Klass identifier used to implement devirtualized oop closure dispatching. - const KlassID _id; + // Klass kind used to resolve the runtime type of the instance. + // - Used to implement devirtualized oop closure dispatching. + // - Various type checking in the JVM + const KlassKind _kind; // Processed access flags, for use by Class.getModifiers. jint _modifier_flags; @@ -186,13 +188,13 @@ private: protected: // Constructor - Klass(KlassID id); - Klass() : _id(KlassID(-1)) { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); } + Klass(KlassKind kind); + Klass() : _kind(KlassKind(-1)) { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); } void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); public: - int id() { return _id; } + int kind() { return _kind; } enum class DefaultsLookupMode { find, skip }; enum class OverpassLookupMode { find, skip }; @@ -614,18 +616,16 @@ protected: } public: #endif - inline bool is_instance_klass() const { return assert_same_query( - layout_helper_is_instance(layout_helper()), - is_instance_klass_slow()); } - inline bool is_array_klass() const { return assert_same_query( - layout_helper_is_array(layout_helper()), - is_array_klass_slow()); } - inline bool is_objArray_klass() const { return assert_same_query( - layout_helper_is_objArray(layout_helper()), - is_objArray_klass_slow()); } - inline bool is_typeArray_klass() const { return assert_same_query( - layout_helper_is_typeArray(layout_helper()), - is_typeArray_klass_slow()); } + + bool is_instance_klass() const { return assert_same_query(_kind <= InstanceClassLoaderKlassKind, is_instance_klass_slow()); } + // Other is anything that is not one of the more specialized kinds of InstanceKlass. + bool is_other_instance_klass() const { return _kind == InstanceKlassKind; } + bool is_reference_instance_klass() const { return _kind == InstanceRefKlassKind; } + bool is_mirror_instance_klass() const { return _kind == InstanceMirrorKlassKind; } + bool is_class_loader_instance_klass() const { return _kind == InstanceClassLoaderKlassKind; } + bool is_array_klass() const { return assert_same_query( _kind >= TypeArrayKlassKind, is_array_klass_slow()); } + bool is_objArray_klass() const { return assert_same_query( _kind == ObjArrayKlassKind, is_objArray_klass_slow()); } + bool is_typeArray_klass() const { return assert_same_query( _kind == TypeArrayKlassKind, is_typeArray_klass_slow()); } #undef assert_same_query // Access flags diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index fab9bd35487f8c606e197924336722c1c4d252a9..a43816476e8771423988da550fb6b7b9ae81bd4b 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -136,7 +136,7 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da return oak; } -ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) { +ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, Kind) { set_dimension(n); set_element_klass(element_klass); diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp index e4bd54b9ed1e4da01f3675c2ea5ada7c08c7a6a0..0c031725e4c6c27bff16e61edda8bfa38b5ce800 100644 --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -37,7 +37,7 @@ class ObjArrayKlass : public ArrayKlass { friend class JVMCIVMStructs; public: - static const KlassID ID = ObjArrayKlassID; + static const KlassKind Kind = ObjArrayKlassKind; private: // If you add a new field that points to any metaspace object, you diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 145929970914d9aac81c9df647d3a5751fa351f5..17e96450cf2a7c8d04ed9cd6cb61a10451ba0cbc 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -134,10 +134,11 @@ void VerifyOopClosure::do_oop(oop* p) { VerifyOopClosure::do_oop_work(p); void VerifyOopClosure::do_oop(narrowOop* p) { VerifyOopClosure::do_oop_work(p); } // type test operations that doesn't require inclusion of oop.inline.hpp. -bool oopDesc::is_instance_noinline() const { return is_instance(); } -bool oopDesc::is_array_noinline() const { return is_array(); } -bool oopDesc::is_objArray_noinline() const { return is_objArray(); } -bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } +bool oopDesc::is_instance_noinline() const { return is_instance(); } +bool oopDesc::is_instanceRef_noinline() const { return is_instanceRef(); } +bool oopDesc::is_array_noinline() const { return is_array(); } +bool oopDesc::is_objArray_noinline() const { return is_objArray(); } +bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } bool oopDesc::has_klass_gap() { // Only has a klass gap when compressed class pointers are used. diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 994bb67703292b7dcbd3fc78ebd709348a5f2c92..08f354a905d88ab89f2c3298b211a3f87390b7af 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -107,16 +107,18 @@ class oopDesc { inline size_t size_given_klass(Klass* klass); // type test operations (inlined in oop.inline.hpp) - inline bool is_instance() const; - inline bool is_array() const; - inline bool is_objArray() const; - inline bool is_typeArray() const; + inline bool is_instance() const; + inline bool is_instanceRef() const; + inline bool is_array() const; + inline bool is_objArray() const; + inline bool is_typeArray() const; // type test operations that don't require inclusion of oop.inline.hpp. - bool is_instance_noinline() const; - bool is_array_noinline() const; - bool is_objArray_noinline() const; - bool is_typeArray_noinline() const; + bool is_instance_noinline() const; + bool is_instanceRef_noinline() const; + bool is_array_noinline() const; + bool is_objArray_noinline() const; + bool is_typeArray_noinline() const; protected: inline oop as_oop() const { return const_cast(this); } diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 17ce5bed5613ce00cc22e5971ab902b19ff3a520..d8ff94178c5d2726074cc98c92b1e00d13c9fc1d 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -195,10 +195,11 @@ size_t oopDesc::size_given_klass(Klass* klass) { return s; } -bool oopDesc::is_instance() const { return klass()->is_instance_klass(); } -bool oopDesc::is_array() const { return klass()->is_array_klass(); } -bool oopDesc::is_objArray() const { return klass()->is_objArray_klass(); } -bool oopDesc::is_typeArray() const { return klass()->is_typeArray_klass(); } +bool oopDesc::is_instance() const { return klass()->is_instance_klass(); } +bool oopDesc::is_instanceRef() const { return klass()->is_reference_instance_klass(); } +bool oopDesc::is_array() const { return klass()->is_array_klass(); } +bool oopDesc::is_objArray() const { return klass()->is_objArray_klass(); } +bool oopDesc::is_typeArray() const { return klass()->is_typeArray_klass(); } template T* oopDesc::field_addr(int offset) const { return reinterpret_cast(cast_from_oop(as_oop()) + offset); } diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp index c79cc61e39a2b765e09235f5c2be48319523559d..fa67b4876d9e4f0a3b36f12c59b9a8cfdd94b212 100644 --- a/src/hotspot/share/oops/typeArrayKlass.cpp +++ b/src/hotspot/share/oops/typeArrayKlass.cpp @@ -75,7 +75,7 @@ TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType return new (loader_data, size, THREAD) TypeArrayKlass(type, name); } -TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, ID) { +TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, Kind) { set_layout_helper(array_layout_helper(type)); assert(is_array_klass(), "sanity"); assert(is_typeArray_klass(), "sanity"); diff --git a/src/hotspot/share/oops/typeArrayKlass.hpp b/src/hotspot/share/oops/typeArrayKlass.hpp index 1ba4613adff1e34df62dc5ab17ba6f5def405f47..389c5ddbd74a5520bd697754443a7b58a6e2579a 100644 --- a/src/hotspot/share/oops/typeArrayKlass.hpp +++ b/src/hotspot/share/oops/typeArrayKlass.hpp @@ -36,7 +36,7 @@ class TypeArrayKlass : public ArrayKlass { friend class VMStructs; public: - static const KlassID ID = TypeArrayKlassID; + static const KlassKind Kind = TypeArrayKlassKind; private: jint _max_length; // maximum number of elements allowed in an array 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..dfa2a86e60281c5823f5b37ee22fa7126bd98a66 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -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; @@ -523,6 +523,8 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_dlog: case vmIntrinsics::_dlog10: case vmIntrinsics::_dpow: + case vmIntrinsics::_roundD: + case vmIntrinsics::_roundF: case vmIntrinsics::_min: case vmIntrinsics::_max: case vmIntrinsics::_min_strict: diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 4abb3fef3b47bc8ba0ad51728a998f567012027e..a268399f1b93cd2c9ef8b1db08a27a2708de6847 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) @@ -311,6 +311,8 @@ macro(SignumD) macro(SignumF) macro(SqrtD) macro(SqrtF) +macro(RoundF) +macro(RoundD) macro(Start) macro(StartOSR) macro(StoreB) @@ -386,6 +388,7 @@ macro(AbsVL) macro(AbsVF) macro(AbsVD) macro(NegVI) +macro(NegVL) macro(NegVF) macro(NegVD) macro(SqrtVD) @@ -445,6 +448,8 @@ macro(ReplicateI) macro(ReplicateL) macro(ReplicateF) macro(ReplicateD) +macro(RoundVF) +macro(RoundVD) macro(Extract) macro(ExtractB) macro(ExtractUB) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index c80eabca43b6ef4a6e1b2394aa41edf2c0e59233..c9567a6be777a18aff42410873520a80d3c5e8a9 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -548,7 +548,13 @@ void Compile::print_ideal_ir(const char* phase_name) { is_osr_compilation() ? " compile_kind='osr'" : "", phase_name); } - root()->dump(9999); + if (_output == nullptr) { + root()->dump(9999); + } else { + // Dump the node blockwise if we have a scheduling + _output->print_scheduling(); + } + if (xtty != NULL) { xtty->tail("ideal"); } @@ -624,7 +630,8 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, _replay_inline_data(NULL), _java_calls(0), _inner_loops(0), - _interpreter_frame_size(0) + _interpreter_frame_size(0), + _output(NULL) #ifndef PRODUCT , _in_dump_cnt(0) #endif @@ -898,6 +905,7 @@ Compile::Compile( ciEnv* ci_env, _java_calls(0), _inner_loops(0), _interpreter_frame_size(0), + _output(NULL), #ifndef PRODUCT _in_dump_cnt(0), #endif diff --git a/src/hotspot/share/opto/convertnode.hpp b/src/hotspot/share/opto/convertnode.hpp index fb670191fc399beacbaf07f19fdf55694b9b841b..87fca38d43fc3a35fcfb6a6fb783d26506dfbc8a 100644 --- a/src/hotspot/share/opto/convertnode.hpp +++ b/src/hotspot/share/opto/convertnode.hpp @@ -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 @@ -81,6 +81,14 @@ class ConvD2LNode : public Node { virtual uint ideal_reg() const { return Op_RegL; } }; +class RoundDNode : public Node { + public: + RoundDNode( Node *dbl ) : Node(0,dbl) {} + virtual int Opcode() const; + virtual const Type *bottom_type() const { return TypeLong::LONG; } + virtual uint ideal_reg() const { return Op_RegL; } +}; + //------------------------------ConvF2DNode------------------------------------ // Convert Float to a Double. class ConvF2DNode : public Node { @@ -105,6 +113,7 @@ class ConvF2INode : public Node { virtual uint ideal_reg() const { return Op_RegI; } }; + //------------------------------ConvF2LNode------------------------------------ // Convert float to long class ConvF2LNode : public Node { @@ -141,6 +150,14 @@ class ConvI2FNode : public Node { virtual uint ideal_reg() const { return Op_RegF; } }; +class RoundFNode : public Node { + public: + RoundFNode( Node *in1 ) : Node(0,in1) {} + virtual int Opcode() const; + virtual const Type *bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + //------------------------------ConvI2LNode------------------------------------ // Convert integer to long class ConvI2LNode : public TypeNode { diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index d9df238aff44d3c11eba77305e9bd7c28c956e5e..3e02b18f50f35e4c66274172259955e1aa41118b 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -635,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: @@ -773,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: @@ -3344,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 || @@ -3475,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(); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index ecee31477879cef2fd3f398d8cafe883b00d678e..2d790399cdb0615a44e80c8598d8eb05034fd7c4 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -526,7 +526,7 @@ void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptR } //------------------------------builtin_throw---------------------------------- -void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) { +void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) { bool must_throw = true; // If this particular condition has not yet happened at this @@ -3334,7 +3334,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, bool is_aastore = (java_bc() == Bytecodes::_aastore); Deoptimization::DeoptReason reason = is_aastore ? Deoptimization::Reason_array_check : Deoptimization::Reason_class_check; - builtin_throw(reason, makecon(TypeKlassPtr::make(objtp->klass()))); + builtin_throw(reason); return top(); } else if (!too_many_traps_or_recompiles(Deoptimization::Reason_null_assert)) { return null_assert(obj); @@ -3419,7 +3419,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, bool is_aastore = (java_bc() == Bytecodes::_aastore); Deoptimization::DeoptReason reason = is_aastore ? Deoptimization::Reason_array_check : Deoptimization::Reason_class_check; - builtin_throw(reason, load_object_klass(not_null_obj)); + builtin_throw(reason); } } else { (*failure_control) = not_subtype_ctrl; diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index b2a85b84f03ac8d0ad425c769ea5ed29e9578195..9ad350d559d1e444e8c618692b144d9db2bc6e59 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -266,12 +266,8 @@ class GraphKit : public Phase { JVMState* transfer_exceptions_into_jvms(); // Helper to throw a built-in exception. - // Range checks take the offending index. - // Cast and array store checks take the offending class. - // Others do not take the optional argument. - // The JVMS must allow the bytecode to be re-executed - // via an uncommon trap. - void builtin_throw(Deoptimization::DeoptReason reason, Node* arg = NULL); + // The JVMS must allow the bytecode to be re-executed via an uncommon trap. + void builtin_throw(Deoptimization::DeoptReason reason); // Helper to check the JavaThread::_should_post_on_exceptions flag // and branch to an uncommon_trap if it is true (with the specified reason and must_throw) 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..fd23e272c71e91b1e7866ea7528af6085dc4f4a1 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.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. * 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,6 +269,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_dcopySign: case vmIntrinsics::_fcopySign: case vmIntrinsics::_dsignum: + case vmIntrinsics::_roundF: + case vmIntrinsics::_roundD: case vmIntrinsics::_fsignum: return inline_math_native(intrinsic_id()); case vmIntrinsics::_notify: @@ -617,8 +619,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 +1013,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 +1033,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 +1094,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; } @@ -1606,6 +1607,7 @@ Node* LibraryCallKit::round_double_node(Node* n) { // public static double Math.sqrt(double) // public static double Math.log(double) // public static double Math.log10(double) +// public static double Math.round(double) bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) { Node* arg = round_double_node(argument(0)); Node* n = NULL; @@ -1617,6 +1619,7 @@ bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) { case vmIntrinsics::_ceil: n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_ceil); break; case vmIntrinsics::_floor: n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_floor); break; case vmIntrinsics::_rint: n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_rint); break; + case vmIntrinsics::_roundD: n = new RoundDNode(arg); break; case vmIntrinsics::_dcopySign: n = CopySignDNode::make(_gvn, arg, round_double_node(argument(2))); break; case vmIntrinsics::_dsignum: n = SignumDNode::make(_gvn, arg); break; default: fatal_unexpected_iid(id); break; @@ -1638,6 +1641,7 @@ bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { case vmIntrinsics::_labs: n = new AbsLNode( arg); break; case vmIntrinsics::_fcopySign: n = new CopySignFNode(arg, argument(1)); break; case vmIntrinsics::_fsignum: n = SignumFNode::make(_gvn, arg); break; + case vmIntrinsics::_roundF: n = new RoundFNode(arg); break; default: fatal_unexpected_iid(id); break; } set_result(_gvn.transform(n)); @@ -1753,9 +1757,11 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); // These intrinsics are supported on all hardware + case vmIntrinsics::_roundD: return Matcher::match_rule_supported(Op_RoundD) ? inline_double_math(id) : false; case vmIntrinsics::_ceil: case vmIntrinsics::_floor: case vmIntrinsics::_rint: return Matcher::match_rule_supported(Op_RoundDoubleMode) ? inline_double_math(id) : false; + case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsqrt_strict: return Matcher::match_rule_supported(Op_SqrtD) ? inline_double_math(id) : false; @@ -1775,6 +1781,7 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { case vmIntrinsics::_fcopySign: return inline_math(id); case vmIntrinsics::_dsignum: return Matcher::match_rule_supported(Op_SignumD) ? inline_double_math(id) : false; case vmIntrinsics::_fsignum: return Matcher::match_rule_supported(Op_SignumF) ? inline_math(id) : false; + case vmIntrinsics::_roundF: return Matcher::match_rule_supported(Op_RoundF) ? inline_math(id) : false; // These intrinsics are not yet correctly implemented case vmIntrinsics::_datan2: 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..a983994166992188d49407ef2b9f0bdbd994c31b 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,22 @@ 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_RoundF: body_size += 30; break; + case Op_RoundD: body_size += 30; break; + case Op_RoundVF: body_size += 30; break; + case Op_RoundVD: body_size += 30; 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 +1132,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 +1158,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 +1958,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 +2539,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 +2742,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, @@ -3932,10 +4051,17 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { index = new LShiftXNode(index, shift->in(2)); _igvn.register_new_node_with_optimizer(index); } - index = new AddPNode(base, base, index); - _igvn.register_new_node_with_optimizer(index); - Node* from = new AddPNode(base, index, offset); + Node* from = new AddPNode(base, base, index); _igvn.register_new_node_with_optimizer(from); + // For normal array fills, C2 uses two AddP nodes for array element + // addressing. But for array fills with Unsafe call, there's only one + // AddP node adding an absolute offset, so we do a NULL check here. + assert(offset != NULL || C->has_unsafe_access(), + "Only array fills with unsafe have no extra offset"); + if (offset != NULL) { + from = new AddPNode(base, from, offset); + _igvn.register_new_node_with_optimizer(from); + } // Compute the number of elements to copy Node* len = new SubINode(head->limit(), head->init_trip()); _igvn.register_new_node_with_optimizer(len); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 25bf93883d974317ede1584c07ab59b000cb571a..28ed035b82b83dbb95afe0f9c51481cff3aaede7 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -852,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); } @@ -1058,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; @@ -1139,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); @@ -1154,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) +// +// R values which are out of range (>Q_max+1) are reduced to max(0,Q_max+1). They are marked on the number line as R<. // -// 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) // -// if both Q_min, Q_max >=s64 0, then use this test: -// j*K + 0 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. +// +// So, if both Q_min, Q_max+1 >=s64 0, then use this test: +// j*K + 0 0 +// More generally: +// j*K + Q - Q_min R> R> R> R | (against R values) +// +// In this case, Q_min >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.) // -// if Q_min >=s64 0 but Q_max =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(); @@ -1266,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); @@ -1279,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); @@ -1315,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); @@ -1342,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); @@ -1990,7 +1995,6 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ Node* entry_control = init_control; bool strip_mine_loop = iv_bt == T_INT && - LoopStripMiningIter > 1 && loop->_child == NULL && sfpt != NULL && !loop->_has_call; @@ -2018,7 +2022,7 @@ 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 (sfpt != NULL && (LoopStripMiningIter != 0 || is_deleteable_safept(sfpt))) { + if (sfpt != NULL && (strip_mine_loop || is_deleteable_safept(sfpt))) { if (strip_mine_loop) { Node* outer_le = outer_ilt->_tail->in(0); Node* sfpt_clone = sfpt->clone(); @@ -2560,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 @@ -2567,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(); @@ -2586,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) { @@ -2671,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 @@ -2834,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) @@ -4468,7 +4568,14 @@ void PhaseIdealLoop::build_and_optimize() { sw.transform_loop(lpt, true); } } else if (cl->is_main_loop()) { - sw.transform_loop(lpt, true); + if (!sw.transform_loop(lpt, true)) { + // Instigate more unrolling for optimization when vectorization fails. + if (cl->has_passed_slp()) { + C->set_major_progress(); + cl->set_notpassed_slp(); + cl->mark_do_unroll_only(); + } + } } } } @@ -5675,7 +5782,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()) { diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 9b9a52f80af0b94a95877847e1668a7db2ddb163..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 { @@ -1265,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; @@ -1282,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 { @@ -1656,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/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 6a03a080c828bb4b2adbccb3f4665d743083a7d9..748db2867100f73b0f3461042378f3fc0510287c 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1153,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; diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 78d1c23a2ceed495f5213b31b97ddb9324aba5fa..dbe95a7c6e69f0c717c304848d9db220824ff812 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -324,6 +324,8 @@ void PhaseOutput::perform_mach_node_analysis() { bs->late_barrier_analysis(); pd_perform_mach_node_analysis(); + + C->print_method(CompilerPhaseType::PHASE_MACHANALYSIS, 4); } // Convert Nodes to instruction bits and pass off to the VM @@ -2117,20 +2119,27 @@ void PhaseOutput::ScheduleAndBundle() { #ifndef PRODUCT if (C->trace_opto_output()) { tty->print("\n---- After ScheduleAndBundle ----\n"); - for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { - tty->print("\nBB#%03d:\n", i); - Block* block = C->cfg()->get_block(i); - for (uint j = 0; j < block->number_of_nodes(); j++) { - Node* n = block->get_node(j); - OptoReg::Name reg = C->regalloc()->get_reg_first(n); - tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : ""); - n->dump(); - } - } + print_scheduling(); } #endif } +#ifndef PRODUCT +// Separated out so that it can be called directly from debugger +void PhaseOutput::print_scheduling() { + for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { + tty->print("\nBB#%03d:\n", i); + Block* block = C->cfg()->get_block(i); + for (uint j = 0; j < block->number_of_nodes(); j++) { + Node* n = block->get_node(j); + OptoReg::Name reg = C->regalloc()->get_reg_first(n); + tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : ""); + n->dump(); + } + } +} +#endif + // See if this node fits into the present instruction bundle bool Scheduling::NodeFitsInBundle(Node *n) { uint n_idx = n->_idx; diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index 4f296c64b8efbca8090475b726078100ea4b8aae..5dca8f772a07ccaf7d04fafac56f462a1921806e 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -263,6 +263,7 @@ public: void BuildOopMaps(); #ifndef PRODUCT + void print_scheduling(); static void print_statistics(); #endif }; diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 4746fd7fafe045eb63e24c5dcd3d5ffadbc7381c..3731dfaa8d20ab44bf6844c61701ec962c5e394c 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -194,7 +194,7 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) { // If we have already recompiled with the range-check-widening // heroic optimization turned off, then we must really be throwing // range check exceptions. - builtin_throw(Deoptimization::Reason_range_check, idx); + builtin_throw(Deoptimization::Reason_range_check); } } } 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/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index d56a7b13197abfaac31fc389ad9d99e604676936..d0415317c008c3f33470823eca27786288ca6848 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -57,6 +57,7 @@ flags(AFTER_BEAUTIFY_LOOPS, "After beautify loops") \ flags(BEFORE_MATCHING, "Before matching") \ flags(MATCHING, "After matching") \ + flags(MACHANALYSIS, "After mach analysis") \ flags(INCREMENTAL_INLINE, "Incremental Inline") \ flags(INCREMENTAL_INLINE_STEP, "Incremental Inline Step") \ flags(INCREMENTAL_INLINE_CLEANUP, "Incremental Inline Cleanup") \ @@ -96,8 +97,8 @@ class CompilerPhaseTypeHelper { static const char* to_description(CompilerPhaseType cpt) { return phase_descriptions[cpt]; } - static int to_bitmask(CompilerPhaseType cpt) { - return (1 << cpt); + static uint64_t to_bitmask(CompilerPhaseType cpt) { + return (UINT64_C(1) << cpt); } }; diff --git a/src/hotspot/share/opto/regmask.hpp b/src/hotspot/share/opto/regmask.hpp index 1694367554d4b9f1173852ebdcfad020504f4319..233dd0da2d7f33d21b2b455a096a902c83cf0593 100644 --- a/src/hotspot/share/opto/regmask.hpp +++ b/src/hotspot/share/opto/regmask.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 @@ -99,7 +99,7 @@ class RegMask { // requirement is internal to the allocator, and independent of any // particular platform. enum { SlotsPerLong = 2, - SlotsPerVecA = 8, + SlotsPerVecA = RISCV_ONLY(4) NOT_RISCV(8), SlotsPerVecS = 1, SlotsPerVecD = 2, SlotsPerVecX = 4, 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/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 1bf4c7a32828243548edf093076af625f9ac6179..1459e3b754183fa32e1003969bc2b277fedd5e43 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -95,38 +95,48 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) : static const bool _do_vector_loop_experimental = false; // Experimental vectorization which uses data from loop unrolling. //------------------------------transform_loop--------------------------- -void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { +bool SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { assert(UseSuperWord, "should be"); // SuperWord only works with power of two vector sizes. int vector_width = Matcher::vector_width_in_bytes(T_BYTE); if (vector_width < 2 || !is_power_of_2(vector_width)) { - return; + return false; } assert(lpt->_head->is_CountedLoop(), "must be"); CountedLoopNode *cl = lpt->_head->as_CountedLoop(); - if (!cl->is_valid_counted_loop(T_INT)) return; // skip malformed counted loop + if (!cl->is_valid_counted_loop(T_INT)) { + return false; // skip malformed counted loop + } bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop()); if (post_loop_allowed) { - if (cl->is_reduction_loop()) return; // no predication mapping + if (cl->is_reduction_loop()) { + return false; // no predication mapping + } Node *limit = cl->limit(); - if (limit->is_Con()) return; // non constant limits only + if (limit->is_Con()) { + return false; // non constant limits only + } // Now check the limit for expressions we do not handle if (limit->is_Add()) { Node *in2 = limit->in(2); if (in2->is_Con()) { int val = in2->get_int(); // should not try to program these cases - if (val < 0) return; + if (val < 0) { + return false; + } } } } // skip any loop that has not been assigned max unroll by analysis if (do_optimization) { - if (SuperWordLoopUnrollAnalysis && cl->slp_max_unroll() == 0) return; + if (SuperWordLoopUnrollAnalysis && cl->slp_max_unroll() == 0) { + return false; + } } // Check for no control flow in body (other than exit) @@ -141,28 +151,32 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { lpt->dump_head(); } #endif - return; + return false; } // Make sure the are no extra control users of the loop backedge if (cl->back_control()->outcnt() != 1) { - return; + return false; } // Skip any loops already optimized by slp - if (cl->is_vectorized_loop()) return; + if (cl->is_vectorized_loop()) { + return false; + } - if (cl->is_unroll_only()) return; + if (cl->is_unroll_only()) { + return false; + } if (cl->is_main_loop()) { // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit)))) CountedLoopEndNode* pre_end = find_pre_loop_end(cl); if (pre_end == NULL) { - return; + return false; } Node* pre_opaq1 = pre_end->limit(); if (pre_opaq1->Opcode() != Op_Opaque1) { - return; + return false; } set_pre_loop_end(pre_end); } @@ -175,9 +189,10 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { // For now, define one block which is the entire loop body set_bb(cl); + bool success = true; if (do_optimization) { assert(_packset.length() == 0, "packset must be empty"); - SLP_extract(); + success = SLP_extract(); if (PostLoopMultiversioning && Matcher::has_predicated_vectors()) { if (cl->is_vectorized_loop() && cl->is_main_loop() && !cl->is_reduction_loop()) { IdealLoopTree *lpt_next = lpt->_next; @@ -192,6 +207,7 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { } } } + return success; } //------------------------------early unrolling analysis------------------------------ @@ -451,7 +467,7 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) { // inserting scalar promotion, vector creation from multiple scalars, and // extraction of scalar values from vectors. // -void SuperWord::SLP_extract() { +bool SuperWord::SLP_extract() { #ifndef PRODUCT if (_do_vector_loop && TraceSuperWord) { @@ -466,7 +482,7 @@ void SuperWord::SLP_extract() { #endif // Ready the block if (!construct_bb()) { - return; // Exit if no interesting nodes or complex graph. + return false; // Exit if no interesting nodes or complex graph. } // build _dg, _disjoint_ptrs @@ -483,7 +499,7 @@ void SuperWord::SLP_extract() { hoist_loads_in_graph(); // this only rebuild the graph; all basic structs need rebuild explicitly if (!construct_bb()) { - return; // Exit if no interesting nodes or complex graph. + return false; // Exit if no interesting nodes or complex graph. } dependence_graph(); compute_max_depth(); @@ -511,7 +527,7 @@ void SuperWord::SLP_extract() { find_adjacent_refs(); if (align_to_ref() == NULL) { - return; // Did not find memory reference to align vectors + return false; // Did not find memory reference to align vectors } extend_packlist(); @@ -563,15 +579,15 @@ void SuperWord::SLP_extract() { // map base types for vector usage compute_vector_element_type(); } else { - return; + return false; } } else { // for some reason we could not map the slp analysis state of the vectorized loop - return; + return false; } } - output(); + return output(); } //------------------------------find_adjacent_refs--------------------------- @@ -2385,17 +2401,11 @@ void SuperWord::print_loop(bool whole) { //------------------------------output--------------------------- // Convert packs into vector node operations -void SuperWord::output() { +bool SuperWord::output() { CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); Compile* C = _phase->C; if (_packset.length() == 0) { - if (cl->is_main_loop()) { - // Instigate more unrolling for optimization when vectorization fails. - C->set_major_progress(); - cl->set_notpassed_slp(); - cl->mark_do_unroll_only(); - } - return; + return false; } #ifndef PRODUCT @@ -2429,7 +2439,7 @@ void SuperWord::output() { if (do_reserve_copy() && !make_reversable.has_reserved()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");}) - return; + return false; } for (int i = 0; i < _block.length(); i++) { @@ -2474,7 +2484,7 @@ void SuperWord::output() { if (val == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2518,7 +2528,7 @@ void SuperWord::output() { if (in1 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2527,7 +2537,7 @@ void SuperWord::output() { if (in2 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2553,6 +2563,7 @@ void SuperWord::output() { opc == Op_AbsF || opc == Op_AbsD || opc == Op_AbsI || opc == Op_AbsL || opc == Op_NegF || opc == Op_NegD || + opc == Op_RoundF || opc == Op_RoundD || opc == Op_PopCountI || opc == Op_PopCountL) { assert(n->req() == 2, "only one input expected"); Node* in = vector_opd(p, 1); @@ -2569,7 +2580,7 @@ void SuperWord::output() { } else if (is_cmov_pack(p)) { if (can_process_post_loop) { // do not refactor of flow in post loop context - return; + return false; } if (!n->is_CMove()) { continue; @@ -2586,7 +2597,7 @@ void SuperWord::output() { if (!bol->is_Bool()) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2602,7 +2613,7 @@ void SuperWord::output() { if (src1 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2610,7 +2621,7 @@ void SuperWord::output() { if (src2 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2634,7 +2645,7 @@ void SuperWord::output() { } else { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2643,7 +2654,7 @@ void SuperWord::output() { if (vn == NULL) { if (do_reserve_copy()){ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2661,7 +2672,7 @@ void SuperWord::output() { // first check if the vector size if the maximum vector which we can use on the machine, // other vector size have reduced values for predicated data mapping. if (vlen_in_bytes != (uint)MaxVectorSize) { - return; + return false; } } @@ -2734,7 +2745,7 @@ void SuperWord::output() { make_reversable.use_new(); } NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);}) - return; + return true; } //------------------------------vector_opd--------------------------- diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index ddddfc83663752b914499dd0b8c676d0c9d8e78e..9c92365865a237b1b9e7e735dba5a6d723447d21 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -286,7 +286,7 @@ class SuperWord : public ResourceObj { public: SuperWord(PhaseIdealLoop* phase); - void transform_loop(IdealLoopTree* lpt, bool do_optimization); + bool transform_loop(IdealLoopTree* lpt, bool do_optimization); void unrolling_analysis(int &local_loop_unroll_factor); @@ -422,7 +422,7 @@ class SuperWord : public ResourceObj { // methods // Extract the superword level parallelism - void SLP_extract(); + bool SLP_extract(); // Find the adjacent memory references and create pack pairs for them. void find_adjacent_refs(); // Tracing support @@ -509,7 +509,7 @@ class SuperWord : public ResourceObj { Node* find_last_mem_state(Node_List* pk, Node* first_mem); // Convert packs into vector node operations - void output(); + bool output(); // Create a vector operand for the nodes in pack p for operand: in(opd_idx) Node* vector_opd(Node_List* p, int opd_idx); // Can code be generated for pack p? diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 39075bd91802295c7b753c36b328023224805dc5..7454be7b9481e1d042e6a4df18098ea58d44962d 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.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 @@ -199,6 +199,16 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", NodeClassNames[sopc], type2name(type), num_elem); } +#endif + return false; + } + } else if (VectorNode::is_vector_integral_negate(sopc)) { + if (!VectorNode::is_vector_integral_negate_supported(sopc, num_elem, type, false)) { +#ifndef PRODUCT + if (C->print_intrinsics()) { + tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support integral vector negate", + NodeClassNames[sopc], type2name(type), num_elem); + } #endif return false; } @@ -277,8 +287,16 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type } if ((mask_use_type & VecMaskUsePred) != 0) { - if (!Matcher::has_predicated_vectors() || - !Matcher::match_rule_supported_vector_masked(sopc, num_elem, type)) { + bool is_supported = false; + if (Matcher::has_predicated_vectors()) { + if (VectorNode::is_vector_integral_negate(sopc)) { + is_supported = VectorNode::is_vector_integral_negate_supported(sopc, num_elem, type, true); + } else { + is_supported = Matcher::match_rule_supported_vector_masked(sopc, num_elem, type); + } + } + + if (!is_supported) { #ifndef PRODUCT if (C->print_intrinsics()) { tty->print_cr("Rejected vector mask predicate using (%s,%s,%d) because architecture does not support it", diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index a5ec2173966b4b30157a69568359336bd5497311..8b385f28f40dfc2ad63e368adda48063889265ab 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -135,7 +135,14 @@ int VectorNode::opcode(int sopc, BasicType bt) { case Op_AbsD: return (bt == T_DOUBLE ? Op_AbsVD : 0); case Op_NegI: - return (bt == T_INT ? Op_NegVI : 0); + switch (bt) { + case T_BYTE: + case T_SHORT: + case T_INT: return Op_NegVI; + default: return 0; + } + case Op_NegL: + return (bt == T_LONG ? Op_NegVL : 0); case Op_NegF: return (bt == T_FLOAT ? Op_NegVF : 0); case Op_NegD: @@ -150,6 +157,10 @@ int VectorNode::opcode(int sopc, BasicType bt) { return (bt == T_FLOAT ? Op_SqrtVF : 0); case Op_SqrtD: return (bt == T_DOUBLE ? Op_SqrtVD : 0); + case Op_RoundF: + return (bt == T_INT ? Op_RoundVF : 0); + case Op_RoundD: + return (bt == T_LONG ? Op_RoundVD : 0); case Op_PopCountI: // Unimplemented for subword types since bit count changes // depending on size of lane (and sign bit). @@ -275,6 +286,9 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) { if (VectorNode::is_vector_rotate(vopc)) { return is_vector_rotate_supported(vopc, vlen, bt); } + if (VectorNode::is_vector_integral_negate(vopc)) { + return is_vector_integral_negate_supported(vopc, vlen, bt, false); + } return vopc > 0 && Matcher::match_rule_supported_vector(vopc, vlen, bt); } return false; @@ -349,6 +363,38 @@ bool VectorNode::is_vector_rotate_supported(int vopc, uint vlen, BasicType bt) { } } +// Check whether the architecture supports the vector negate instructions. If not, then check +// whether the alternative vector nodes used to implement vector negation are supported. +// Return false if neither of them is supported. +bool VectorNode::is_vector_integral_negate_supported(int opc, uint vlen, BasicType bt, bool use_predicate) { + if (!use_predicate) { + // Check whether the NegVI/L is supported by the architecture. + if (Matcher::match_rule_supported_vector(opc, vlen, bt)) { + return true; + } + // Negate is implemented with "(SubVI/L (ReplicateI/L 0) src)", if NegVI/L is not supported. + int sub_opc = (bt == T_LONG) ? Op_SubL : Op_SubI; + if (Matcher::match_rule_supported_vector(VectorNode::opcode(sub_opc, bt), vlen, bt) && + Matcher::match_rule_supported_vector(VectorNode::replicate_opcode(bt), vlen, bt)) { + return true; + } + } else { + // Check whether the predicated NegVI/L is supported by the architecture. + if (Matcher::match_rule_supported_vector_masked(opc, vlen, bt)) { + return true; + } + // Predicated negate is implemented with "(AddVI/L (XorV src (ReplicateI/L -1)) (ReplicateI/L 1))", + // if predicated NegVI/L is not supported. + int add_opc = (bt == T_LONG) ? Op_AddL : Op_AddI; + if (Matcher::match_rule_supported_vector_masked(Op_XorV, vlen, bt) && + Matcher::match_rule_supported_vector_masked(VectorNode::opcode(add_opc, bt), vlen, bt) && + Matcher::match_rule_supported_vector(VectorNode::replicate_opcode(bt), vlen, bt)) { + return true; + } + } + return false; +} + bool VectorNode::is_shift_opcode(int opc) { switch (opc) { case Op_LShiftI: @@ -536,12 +582,16 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b case Op_AbsVL: return new AbsVLNode(n1, vt); case Op_NegVI: return new NegVINode(n1, vt); + case Op_NegVL: return new NegVLNode(n1, vt); case Op_NegVF: return new NegVFNode(n1, vt); case Op_NegVD: return new NegVDNode(n1, vt); case Op_SqrtVF: return new SqrtVFNode(n1, vt); case Op_SqrtVD: return new SqrtVDNode(n1, vt); + case Op_RoundVF: return new RoundVFNode(n1, vt); + case Op_RoundVD: return new RoundVDNode(n1, vt); + case Op_PopCountVI: return new PopCountVINode(n1, vt); case Op_PopCountVL: return new PopCountVLNode(n1, vt); case Op_RotateLeftV: return new RotateLeftVNode(n1, n2, vt); @@ -667,6 +717,10 @@ bool VectorNode::is_vector_rotate(int opc) { } } +bool VectorNode::is_vector_integral_negate(int opc) { + return opc == Op_NegVI || opc == Op_NegVL; +} + bool VectorNode::is_vector_shift(int opc) { assert(opc > _last_machine_leaf && opc < _last_opcode, "invalid opcode"); switch (opc) { @@ -1541,6 +1595,69 @@ Node* VectorLongToMaskNode::Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; } +// Generate other vector nodes to implement the masked/non-masked vector negation. +Node* NegVNode::degenerate_integral_negate(PhaseGVN* phase, bool is_predicated) { + const TypeVect* vt = vect_type(); + BasicType bt = vt->element_basic_type(); + uint vlen = length(); + + // Transformation for predicated NegVI/L + if (is_predicated) { + // (NegVI/L src m) ==> (AddVI/L (XorV src (ReplicateI/L -1) m) (ReplicateI/L 1) m) + Node* const_minus_one = NULL; + Node* const_one = NULL; + int add_opc; + if (bt == T_LONG) { + const_minus_one = phase->longcon(-1L); + const_one = phase->longcon(1L); + add_opc = Op_AddL; + } else { + const_minus_one = phase->intcon(-1); + const_one = phase->intcon(1); + add_opc = Op_AddI; + } + const_minus_one = phase->transform(VectorNode::scalar2vector(const_minus_one, vlen, Type::get_const_basic_type(bt))); + Node* xorv = VectorNode::make(Op_XorV, in(1), const_minus_one, vt); + xorv->add_req(in(2)); + xorv->add_flag(Node::Flag_is_predicated_vector); + phase->transform(xorv); + const_one = phase->transform(VectorNode::scalar2vector(const_one, vlen, Type::get_const_basic_type(bt))); + Node* addv = VectorNode::make(VectorNode::opcode(add_opc, bt), xorv, const_one, vt); + addv->add_req(in(2)); + addv->add_flag(Node::Flag_is_predicated_vector); + return addv; + } + + // NegVI/L ==> (SubVI/L (ReplicateI/L 0) src) + Node* const_zero = NULL; + int sub_opc; + if (bt == T_LONG) { + const_zero = phase->longcon(0L); + sub_opc = Op_SubL; + } else { + const_zero = phase->intcon(0); + sub_opc = Op_SubI; + } + const_zero = phase->transform(VectorNode::scalar2vector(const_zero, vlen, Type::get_const_basic_type(bt))); + return VectorNode::make(VectorNode::opcode(sub_opc, bt), const_zero, in(1), vt); +} + +Node* NegVNode::Ideal(PhaseGVN* phase, bool can_reshape) { + BasicType bt = vect_type()->element_basic_type(); + uint vlen = length(); + int opc = Opcode(); + if (is_vector_integral_negate(opc)) { + if (is_predicated_vector()) { + if (!Matcher::match_rule_supported_vector_masked(opc, vlen, bt)) { + return degenerate_integral_negate(phase, true); + } + } else if (!Matcher::match_rule_supported_vector(opc, vlen, bt)) { + return degenerate_integral_negate(phase, false); + } + } + return NULL; +} + #ifndef PRODUCT void VectorBoxAllocateNode::dump_spec(outputStream *st) const { CallStaticJavaNode::dump_spec(st); diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 4853d719ce0ff6d7cc62e7e9082749268306f12f..74fd1f63991ed91f6d1a8f71c1aef5deab329ee6 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -97,6 +97,7 @@ class VectorNode : public TypeNode { static bool is_roundopD(Node* n); static bool is_scalar_rotate(Node* n); static bool is_vector_rotate_supported(int opc, uint vlen, BasicType bt); + static bool is_vector_integral_negate_supported(int opc, uint vlen, BasicType bt, bool use_predicate); static bool is_invariant_vector(Node* n); static bool is_all_ones_vector(Node* n); static bool is_vector_bitwise_not_pattern(Node* n); @@ -109,6 +110,7 @@ class VectorNode : public TypeNode { static bool is_vector_shift(int opc); static bool is_vector_shift_count(int opc); static bool is_vector_rotate(int opc); + static bool is_vector_integral_negate(int opc); static bool is_vector_shift(Node* n) { return is_vector_shift(n->Opcode()); @@ -474,27 +476,47 @@ class AbsVDNode : public VectorNode { virtual int Opcode() const; }; +//------------------------------NegVNode--------------------------------------- +// Vector Neg parent class (not for code generation). +class NegVNode : public VectorNode { + public: + NegVNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const = 0; + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + + private: + Node* degenerate_integral_negate(PhaseGVN* phase, bool is_predicated); +}; + //------------------------------NegVINode-------------------------------------- -// Vector Neg int -class NegVINode : public VectorNode { +// Vector Neg byte/short/int +class NegVINode : public NegVNode { public: - NegVINode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + NegVINode(Node* in, const TypeVect* vt) : NegVNode(in, vt) {} + virtual int Opcode() const; +}; + +//------------------------------NegVLNode-------------------------------------- +// Vector Neg long +class NegVLNode : public NegVNode { + public: + NegVLNode(Node* in, const TypeVect* vt) : NegVNode(in, vt) {} virtual int Opcode() const; }; //------------------------------NegVFNode-------------------------------------- // Vector Neg float -class NegVFNode : public VectorNode { +class NegVFNode : public NegVNode { public: - NegVFNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} + NegVFNode(Node* in, const TypeVect* vt) : NegVNode(in, vt) {} virtual int Opcode() const; }; //------------------------------NegVDNode-------------------------------------- // Vector Neg double -class NegVDNode : public VectorNode { +class NegVDNode : public NegVNode { public: - NegVDNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} + NegVDNode(Node* in, const TypeVect* vt) : NegVNode(in, vt) {} virtual int Opcode() const; }; @@ -1522,6 +1544,14 @@ class VectorCastD2XNode : public VectorCastNode { virtual int Opcode() const; }; +class RoundVFNode : public VectorNode { + public: + RoundVFNode(Node* in, const TypeVect* vt) :VectorNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == T_FLOAT, "must be float"); + } + virtual int Opcode() const; +}; + class VectorUCastB2XNode : public VectorCastNode { public: VectorUCastB2XNode(Node* in, const TypeVect* vt) : VectorCastNode(in, vt) { @@ -1530,6 +1560,14 @@ class VectorUCastB2XNode : public VectorCastNode { virtual int Opcode() const; }; +class RoundVDNode : public VectorNode { + public: + RoundVDNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE, "must be double"); + } + virtual int Opcode() const; +}; + class VectorUCastS2XNode : public VectorCastNode { public: VectorUCastS2XNode(Node* in, const TypeVect* vt) : VectorCastNode(in, vt) { diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index 13a2ff9dc8718def636c3eec9c6c5475ab04472c..d60edaf03f777973dfc6f24bf7a7ed7ca91866c1 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -549,7 +549,9 @@ JNI_END static void jni_check_async_exceptions(JavaThread *thread) { assert(thread == Thread::current(), "must be itself"); - thread->check_and_handle_async_exceptions(); + if (thread->has_async_exception_condition()) { + SafepointMechanism::process_if_requested_with_exit_check(thread, true /* check asyncs */); + } } JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env)) 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/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 84cd940a5630237565649b1a9a654aeab256ca94..a43355181c9ff9872f0116b477603c4349934af7 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/instanceKlass.hpp" @@ -3380,7 +3381,7 @@ JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) { int readable_count = 0; // Loop through the system properties until all the readable properties are found. for (SystemProperty* p = Arguments::system_properties(); p != NULL && readable_count < *count_ptr; p = p->next()) { - if (p->is_readable()) { + if (p->readable()) { const char *key = p->key(); char **tmp_value = *property_ptr+readable_count; readable_count++; @@ -3427,14 +3428,21 @@ JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) { // value - NULL is a valid value, must be checked jvmtiError JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { - jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE; - for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { if (strcmp(property, p->key()) == 0) { - if (p->set_writeable_value(value_ptr)) { - err = JVMTI_ERROR_NONE; + if (p->writeable()) { + if (p->set_value(value_ptr, AllocFailStrategy::RETURN_NULL)) { + return JVMTI_ERROR_NONE; + } else { + return JVMTI_ERROR_OUT_OF_MEMORY; + } + } else { + // We found a property, but it's not writeable + return JVMTI_ERROR_NOT_AVAILABLE; } } } - return err; + + // We cannot find a property of the given name + return JVMTI_ERROR_NOT_AVAILABLE; } /* end SetSystemProperty */ 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 319f1eba26bf3254fe5e013b3e68d7e98ce5faad..41fada6988b1550cfc42cf4a11b5fe7a856430cc 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -183,7 +183,8 @@ const char* Abstract_VM_Version::jre_release_version() { AMD64_ONLY("amd64") \ IA32_ONLY("x86") \ IA64_ONLY("ia64") \ - S390_ONLY("s390") + S390_ONLY("s390") \ + RISCV64_ONLY("riscv64") #endif // !ZERO #endif // !CPU diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index a38e70b0b26aec30d3b481025cd67ff0d34eae56..06cc989278aac79ad0fedf6d1818321c16d4a6e8 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" @@ -122,18 +125,17 @@ char* Arguments::_ext_dirs = NULL; // True if -Xshare:auto option was specified. static bool xshare_auto_cmd_line = false; -bool PathString::set_value(const char *value) { - if (_value != NULL) { - FreeHeap(_value); +bool PathString::set_value(const char *value, AllocFailType alloc_failmode) { + char* new_value = AllocateHeap(strlen(value)+1, mtArguments, alloc_failmode); + if (new_value == NULL) { + assert(alloc_failmode == AllocFailStrategy::RETURN_NULL, "must be"); + return false; } - _value = AllocateHeap(strlen(value)+1, mtArguments); - assert(_value != NULL, "Unable to allocate space for new path value"); if (_value != NULL) { - strcpy(_value, value); - } else { - // not able to allocate - return false; + FreeHeap(_value); } + _value = new_value; + strcpy(_value, value); return true; } @@ -744,20 +746,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; +} + +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; + } +} - // First char must be a digit. Don't allow negative numbers or leading spaces. - if (!isdigit(*s)) { +// 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; } @@ -768,28 +834,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) { @@ -824,13 +891,21 @@ static bool set_bool_flag(JVMFlag* flag, bool value, JVMFlagOrigin origin) { } } -static bool set_fp_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin) { +static bool set_fp_numeric_flag(JVMFlag* flag, const char* value, JVMFlagOrigin origin) { + // strtod allows leading whitespace, but our flag format does not. + if (*value == '\0' || isspace(*value)) { + return false; + } char* end; errno = 0; double v = strtod(value, &end); if ((errno != 0) || (*end != 0)) { return false; } + if (g_isnan(v) || !g_isfinite(v)) { + // Currently we cannot handle these special values. + return false; + } if (JVMFlagAccess::set_double(flag, &v, origin) == JVMFlag::SUCCESS) { return true; @@ -838,75 +913,48 @@ 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; - - if (flag == NULL) { - return false; - } +static bool set_numeric_flag(JVMFlag* flag, const char* value, JVMFlagOrigin origin) { + JVMFlag::Error result = JVMFlag::WRONG_FORMAT; - // 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)) { + result = JVMFlagAccess::set_int(flag, &v, origin); } - if ((!is_neg && v > max_jint) || (is_neg && -(intx)v < min_jint)) { - return false; - } - return JVMFlagAccess::set_int(flag, &int_v, origin) == JVMFlag::SUCCESS; } else if (flag->is_uint()) { - if (v > max_juint) { - return false; + uint v; + if (parse_integer(value, &v)) { + result = JVMFlagAccess::set_uint(flag, &v, origin); } - uint uint_v = (uint) v; - return JVMFlagAccess::set_uint(flag, &uint_v, origin) == JVMFlag::SUCCESS; } else if (flag->is_intx()) { - intx_v = (intx) v; - if (is_neg) { - if (intx_v != min_intx) { - intx_v = - intx_v; - if (intx_v > 0) { - return false; // underflow - } - } - } else { - if (intx_v < 0) { - return false; // overflow - } + intx v; + if (parse_integer(value, &v)) { + result = 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)) { + result = 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)) { + result = 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; - } else if (flag->is_double()) { - double double_v = (double) v; - return JVMFlagAccess::set_double(flag, &double_v, origin) == JVMFlag::SUCCESS; - } else { - return false; + size_t v; + if (parse_integer(value, &v)) { + result = JVMFlagAccess::set_size_t(flag, &v, origin); + } } + + return result == JVMFlag::SUCCESS; } static bool set_string_flag(JVMFlag* flag, const char* value, JVMFlagOrigin origin) { + if (value[0] == '\0') { + value = NULL; + } if (JVMFlagAccess::set_ccstr(flag, &value, origin) != JVMFlag::SUCCESS) return false; // Contract: JVMFlag always returns a pointer that needs freeing. FREE_C_HEAP_ARRAY(char, value); @@ -940,7 +988,7 @@ static bool append_to_string_flag(JVMFlag* flag, const char* new_value, JVMFlagO return true; } -const char* Arguments::handle_aliases_and_deprecation(const char* arg, bool warn) { +const char* Arguments::handle_aliases_and_deprecation(const char* arg) { const char* real_name = real_flag_name(arg); JDK_Version since = JDK_Version(); switch (is_deprecated_flag(arg, &since)) { @@ -958,16 +1006,14 @@ const char* Arguments::handle_aliases_and_deprecation(const char* arg, bool warn case 0: return real_name; case 1: { - if (warn) { - char version[256]; - since.to_string(version, sizeof(version)); - if (real_name != arg) { - warning("Option %s was deprecated in version %s and will likely be removed in a future release. Use option %s instead.", - arg, version, real_name); - } else { - warning("Option %s was deprecated in version %s and will likely be removed in a future release.", - arg, version); - } + char version[256]; + since.to_string(version, sizeof(version)); + if (real_name != arg) { + warning("Option %s was deprecated in version %s and will likely be removed in a future release. Use option %s instead.", + arg, version, real_name); + } else { + warning("Option %s was deprecated in version %s and will likely be removed in a future release.", + arg, version); } return real_name; } @@ -976,98 +1022,87 @@ const char* Arguments::handle_aliases_and_deprecation(const char* arg, bool warn return NULL; } -bool Arguments::parse_argument(const char* arg, JVMFlagOrigin origin) { - - // range of acceptable characters spelled out for portability reasons -#define NAME_RANGE "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]" #define BUFLEN 255 - char name[BUFLEN+1]; - char dummy; - const char* real_name; - bool warn_if_deprecated = true; - if (sscanf(arg, "-%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) { - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { - return false; +JVMFlag* Arguments::find_jvm_flag(const char* name, size_t name_length) { + char name_copied[BUFLEN+1]; + if (name[name_length] != 0) { + if (name_length > BUFLEN) { + return NULL; + } else { + strncpy(name_copied, name, name_length); + name_copied[name_length] = '\0'; + name = name_copied; } - JVMFlag* flag = JVMFlag::find_flag(real_name); - return set_bool_flag(flag, false, origin); } - if (sscanf(arg, "+%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) { - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { - return false; + + const char* real_name = Arguments::handle_aliases_and_deprecation(name); + if (real_name == NULL) { + return NULL; + } + JVMFlag* flag = JVMFlag::find_flag(real_name); + return flag; +} + +bool Arguments::parse_argument(const char* arg, JVMFlagOrigin origin) { + bool is_bool = false; + bool bool_val = false; + char c = *arg; + if (c == '+' || c == '-') { + is_bool = true; + bool_val = (c == '+'); + arg++; + } + + const char* name = arg; + while (true) { + c = *arg; + if (isalnum(c) || (c == '_')) { + ++arg; + } else { + break; } - JVMFlag* flag = JVMFlag::find_flag(real_name); - return set_bool_flag(flag, true, origin); } - char punct; - if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "%c", name, &punct) == 2 && punct == '=') { - const char* value = strchr(arg, '=') + 1; + size_t name_len = size_t(arg - name); + if (name_len == 0) { + return false; + } + + JVMFlag* flag = find_jvm_flag(name, name_len); + if (flag == NULL) { + return false; + } - // this scanf pattern matches both strings (handled here) and numbers (handled later)) - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { + if (is_bool) { + if (*arg != 0) { + // Error -- extra characters such as -XX:+BoolFlag=123 return false; } - JVMFlag* flag = JVMFlag::find_flag(real_name); - if (flag != NULL && flag->is_ccstr()) { + return set_bool_flag(flag, bool_val, origin); + } + + if (arg[0] == '=') { + const char* value = arg + 1; + if (flag->is_ccstr()) { if (flag->ccstr_accumulates()) { return append_to_string_flag(flag, value, origin); } else { - if (value[0] == '\0') { - value = NULL; - } return set_string_flag(flag, value, origin); } + } else if (flag->is_double()) { + return set_fp_numeric_flag(flag, value, origin); } else { - warn_if_deprecated = false; // if arg is deprecated, we've already done warning... + return set_numeric_flag(flag, value, origin); } } - if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE ":%c", name, &punct) == 2 && punct == '=') { - const char* value = strchr(arg, '=') + 1; + if (arg[0] == ':' && arg[1] == '=') { // -XX:Foo:=xxx will reset the string flag to the given value. - if (value[0] == '\0') { - value = NULL; - } - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { - return false; - } - JVMFlag* flag = JVMFlag::find_flag(real_name); + const char* value = arg + 2; return set_string_flag(flag, value, origin); } -#define SIGNED_FP_NUMBER_RANGE "[-0123456789.eE+]" -#define SIGNED_NUMBER_RANGE "[-0123456789]" -#define NUMBER_RANGE "[0123456789eE+-]" - char value[BUFLEN + 1]; - char value2[BUFLEN + 1]; - if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "=" "%" XSTR(BUFLEN) SIGNED_NUMBER_RANGE "." "%" XSTR(BUFLEN) NUMBER_RANGE "%c", name, value, value2, &dummy) == 3) { - // Looks like a floating-point number -- try again with more lenient format string - if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "=" "%" XSTR(BUFLEN) SIGNED_FP_NUMBER_RANGE "%c", name, value, &dummy) == 2) { - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { - return false; - } - JVMFlag* flag = JVMFlag::find_flag(real_name); - return set_fp_numeric_flag(flag, value, origin); - } - } - -#define VALUE_RANGE "[-kmgtxKMGTX0123456789abcdefABCDEF]" - if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "=" "%" XSTR(BUFLEN) VALUE_RANGE "%c", name, value, &dummy) == 2) { - real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); - if (real_name == NULL) { - return false; - } - JVMFlag* flag = JVMFlag::find_flag(real_name); - return set_numeric_flag(flag, value, origin); - } - return false; } @@ -2032,7 +2067,7 @@ bool Arguments::check_vm_args_consistency() { } #endif -#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) +#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) && !defined(RISCV64) if (UseHeavyMonitors) { jio_fprintf(defaultStream::error_stream(), "UseHeavyMonitors is not fully implemented on this architecture"); @@ -2082,24 +2117,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) { @@ -2150,7 +2177,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); } @@ -4209,7 +4236,7 @@ int Arguments::PropertyList_count(SystemProperty* pl) { int Arguments::PropertyList_readable_count(SystemProperty* pl) { int count = 0; while(pl != NULL) { - if (pl->is_readable()) { + if (pl->readable()) { count++; } pl = pl->next(); diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 7910b366b38f1fcaa94b90e74fc19235aeaaf77b..abbbaee6fd0d9f4345134b8aea9d54f621aa9d61 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -28,6 +28,7 @@ #include "logging/logLevel.hpp" #include "logging/logTag.hpp" #include "memory/allStatic.hpp" +#include "memory/allocation.hpp" #include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -36,6 +37,8 @@ // Arguments parses the command line and recognizes options +class JVMFlag; + // Invocation API hook typedefs (these should really be defined in jni.h) extern "C" { typedef void (JNICALL *abort_hook_t)(void); @@ -66,7 +69,8 @@ class PathString : public CHeapObj { public: char* value() const { return _value; } - bool set_value(const char *value); + // return false iff OOM && alloc_failmode == AllocFailStrategy::RETURN_NULL + bool set_value(const char *value, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); void append_value(const char *value); PathString(const char* value); @@ -98,7 +102,6 @@ class SystemProperty : public PathString { SystemProperty* _next; bool _internal; bool _writeable; - bool writeable() { return _writeable; } public: // Accessors @@ -107,8 +110,9 @@ class SystemProperty : public PathString { bool internal() const { return _internal; } SystemProperty* next() const { return _next; } void set_next(SystemProperty* next) { _next = next; } + bool writeable() const { return _writeable; } - bool is_readable() const { + bool readable() const { return !_internal || (strcmp(_key, "jdk.boot.class.path.append") == 0 && value() != NULL); } @@ -120,11 +124,10 @@ class SystemProperty : public PathString { // via -Xbootclasspath/a or JVMTI OnLoad phase call to AddToBootstrapClassLoaderSearch. // In those cases for jdk.boot.class.path.append, the base class // set_value and append_value methods are called directly. - bool set_writeable_value(const char *value) { + void set_writeable_value(const char *value) { if (writeable()) { - return set_value(value); + set_value(value); } - return false; } void append_writeable_value(const char *value) { if (writeable()) { @@ -463,10 +466,11 @@ class Arguments : AllStatic { // Return the real name for the flag passed on the command line (either an alias name or "flag_name"). static const char* real_flag_name(const char *flag_name); + static JVMFlag* find_jvm_flag(const char* name, size_t name_length); // Return the "real" name for option arg if arg is an alias, and print a warning if arg is deprecated. // Return NULL if the arg has expired. - static const char* handle_aliases_and_deprecation(const char* arg, bool warn); + static const char* handle_aliases_and_deprecation(const char* arg); static char* SharedArchivePath; static char* SharedDynamicArchivePath; 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.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/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index 05306bd6f3ab6ee5c6cc188cc8a2cfb813fb3eba..c2f91016b4b014e572fff27d70998d24b742b576 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "jvm_io.h" +#include "classfile/javaClasses.hpp" +#include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" @@ -78,6 +80,8 @@ class HandshakeOperation : public CHeapObj { const char* name() { return _handshake_cl->name(); } bool is_async() { return _handshake_cl->is_async(); } bool is_suspend() { return _handshake_cl->is_suspend(); } + bool is_async_exception() { return _handshake_cl->is_async_exception(); } + bool is_ThreadDeath() { return _handshake_cl->is_ThreadDeath(); } }; class AsyncHandshakeOperation : public HandshakeOperation { @@ -313,7 +317,6 @@ void HandshakeOperation::do_handshake(JavaThread* thread) { // Only actually execute the operation for non terminated threads. if (!thread->is_terminated()) { - NoSafepointVerifier nsv; _handshake_cl->do_thread(thread); } @@ -426,6 +429,7 @@ HandshakeState::HandshakeState(JavaThread* target) : _queue(), _lock(Monitor::nosafepoint, "HandshakeState_lock"), _active_handshaker(), + _async_exceptions_blocked(false), _suspended(false), _async_suspend_handshake(false) { @@ -443,39 +447,61 @@ bool HandshakeState::operation_pending(HandshakeOperation* op) { return _queue.contains(mo); } -static bool no_suspend_filter(HandshakeOperation* op) { - return !op->is_suspend(); +// Filters +static bool non_self_executable_filter(HandshakeOperation* op) { + return !op->is_async(); +} +static bool no_async_exception_filter(HandshakeOperation* op) { + return !op->is_async_exception(); +} +static bool async_exception_filter(HandshakeOperation* op) { + return op->is_async_exception(); +} +static bool is_ThreadDeath_filter(HandshakeOperation* op) { + return op->is_ThreadDeath(); +} +static bool no_suspend_no_async_exception_filter(HandshakeOperation* op) { + return !op->is_suspend() && !op->is_async_exception(); } -HandshakeOperation* HandshakeState::get_op_for_self(bool allow_suspend) { +HandshakeOperation* HandshakeState::get_op_for_self(bool allow_suspend, bool check_async_exception) { assert(_handshakee == Thread::current(), "Must be called by self"); assert(_lock.owned_by_self(), "Lock must be held"); - if (allow_suspend) { + assert(allow_suspend || !check_async_exception, "invalid case"); + if (!allow_suspend) { + return _queue.peek(no_suspend_no_async_exception_filter); + } else if (check_async_exception && !_async_exceptions_blocked) { return _queue.peek(); } else { - return _queue.peek(no_suspend_filter); + return _queue.peek(no_async_exception_filter); } } -static bool non_self_queue_filter(HandshakeOperation* op) { - return !op->is_async(); +bool HandshakeState::has_operation(bool allow_suspend, bool check_async_exception) { + MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); + return get_op_for_self(allow_suspend, check_async_exception) != NULL; +} + +bool HandshakeState::has_async_exception_operation(bool ThreadDeath_only) { + if (!has_operation()) return false; + MutexLocker ml(_lock.owned_by_self() ? NULL : &_lock, Mutex::_no_safepoint_check_flag); + if (!ThreadDeath_only) { + return _queue.peek(async_exception_filter) != NULL; + } else { + return _queue.peek(is_ThreadDeath_filter) != NULL; + } } bool HandshakeState::have_non_self_executable_operation() { assert(_handshakee != Thread::current(), "Must not be called by self"); assert(_lock.owned_by_self(), "Lock must be held"); - return _queue.contains(non_self_queue_filter); -} - -bool HandshakeState::has_a_non_suspend_operation() { - MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); - return _queue.contains(no_suspend_filter); + return _queue.contains(non_self_executable_filter); } HandshakeOperation* HandshakeState::get_op() { assert(_handshakee != Thread::current(), "Must not be called by self"); assert(_lock.owned_by_self(), "Lock must be held"); - return _queue.peek(non_self_queue_filter); + return _queue.peek(non_self_executable_filter); }; void HandshakeState::remove_op(HandshakeOperation* op) { @@ -485,7 +511,7 @@ void HandshakeState::remove_op(HandshakeOperation* op) { assert(ret == op, "Popped op must match requested op"); }; -bool HandshakeState::process_by_self(bool allow_suspend) { +bool HandshakeState::process_by_self(bool allow_suspend, bool check_async_exception) { assert(Thread::current() == _handshakee, "should call from _handshakee"); assert(!_handshakee->is_terminated(), "should not be a terminated thread"); @@ -493,15 +519,12 @@ bool HandshakeState::process_by_self(bool allow_suspend) { // Threads shouldn't block if they are in the middle of printing, but... ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id()); - // Handshakes cannot safely safepoint. - // The exception to this rule is the asynchronous suspension handshake. - // It by-passes the NSV by manually doing the transition. - NoSafepointVerifier nsv; - while (has_operation()) { + // Handshakes cannot safely safepoint. The exceptions to this rule are + // the asynchronous suspension and unsafe access error handshakes. MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); - HandshakeOperation* op = get_op_for_self(allow_suspend); + HandshakeOperation* op = get_op_for_self(allow_suspend, check_async_exception); if (op != NULL) { assert(op->_target == NULL || op->_target == Thread::current(), "Wrong thread"); bool async = op->is_async(); @@ -517,8 +540,8 @@ bool HandshakeState::process_by_self(bool allow_suspend) { // An asynchronous handshake may put the JavaThread in blocked state (safepoint safe). // The destructor ~PreserveExceptionMark touches the exception oop so it must not be executed, // since a safepoint may be in-progress when returning from the async handshake. - op->do_handshake(_handshakee); // acquire, op removed after remove_op(op); + op->do_handshake(_handshakee); log_handshake_info(((AsyncHandshakeOperation*)op)->start_time(), op->name(), 1, 0, "asynchronous"); delete op; return true; // Must check for safepoints @@ -730,3 +753,29 @@ bool HandshakeState::resume() { _lock.notify(); return true; } + +void HandshakeState::handle_unsafe_access_error() { + if (is_suspended()) { + // A suspend handshake was added to the queue after the + // unsafe access error. Since the suspender has already + // considered this JT as suspended and assumes it won't go + // back to Java until resumed we cannot create the exception + // object yet. Add a new unsafe access error operation to + // the end of the queue and try again in the next attempt. + Handshake::execute(new UnsafeAccessErrorHandshake(), _handshakee); + log_info(handshake)("JavaThread " INTPTR_FORMAT " skipping unsafe access processing due to suspend.", p2i(_handshakee)); + return; + } + // Release the handshake lock before constructing the oop to + // avoid deadlocks since that can block. This will allow the + // JavaThread to execute normally as if it was outside a handshake. + // We will reacquire the handshake lock at return from ~MutexUnlocker. + MutexUnlocker ml(&_lock, Mutex::_no_safepoint_check_flag); + // We may be at method entry which requires we save the do-not-unlock flag. + UnlockFlagSaver fs(_handshakee); + Handle h_exception = Exceptions::new_exception(_handshakee, vmSymbols::java_lang_InternalError(), "a fault occurred in an unsafe memory access operation"); + if (h_exception()->is_a(vmClasses::InternalError_klass())) { + java_lang_InternalError::set_during_unsafe_access(h_exception()); + } + _handshakee->handle_async_exception(h_exception()); +} diff --git a/src/hotspot/share/runtime/handshake.hpp b/src/hotspot/share/runtime/handshake.hpp index f6a8e28a0378a6e26e8e2a4b6a7f304283ac183b..8012f225c651dc68fcafc11cb30c53e54ccd34b6 100644 --- a/src/hotspot/share/runtime/handshake.hpp +++ b/src/hotspot/share/runtime/handshake.hpp @@ -33,9 +33,11 @@ #include "utilities/filterQueue.hpp" class HandshakeOperation; +class AsyncHandshakeOperation; class JavaThread; class SuspendThreadHandshake; class ThreadSelfSuspensionHandshake; +class UnsafeAccessErrorHandshake; class ThreadsListHandle; // A handshake closure is a callback that is executed for a JavaThread @@ -51,6 +53,8 @@ class HandshakeClosure : public ThreadClosure, public CHeapObj { const char* name() const { return _name; } virtual bool is_async() { return false; } virtual bool is_suspend() { return false; } + virtual bool is_async_exception() { return false; } + virtual bool is_ThreadDeath() { return false; } virtual void do_thread(Thread* thread) = 0; }; @@ -87,6 +91,7 @@ class JvmtiRawMonitor; class HandshakeState { friend ThreadSelfSuspensionHandshake; friend SuspendThreadHandshake; + friend UnsafeAccessErrorHandshake; friend JavaThread; // This a back reference to the JavaThread, // the target for all operation in the queue. @@ -104,7 +109,7 @@ class HandshakeState { bool can_process_handshake(); bool have_non_self_executable_operation(); - HandshakeOperation* get_op_for_self(bool allow_suspend); + HandshakeOperation* get_op_for_self(bool allow_suspend, bool check_async_exception); HandshakeOperation* get_op(); void remove_op(HandshakeOperation* op); @@ -124,17 +129,16 @@ class HandshakeState { void add_operation(HandshakeOperation* op); - bool has_operation() { - return !_queue.is_empty(); - } - bool has_a_non_suspend_operation(); + bool has_operation() { return !_queue.is_empty(); } + bool has_operation(bool allow_suspend, bool check_async_exception); + bool has_async_exception_operation(bool ThreadDeath_only); bool operation_pending(HandshakeOperation* op); // If the method returns true we need to check for a possible safepoint. // This is due to a suspension handshake which put the JavaThread in blocked // state so a safepoint may be in-progress. - bool process_by_self(bool allow_suspend); + bool process_by_self(bool allow_suspend, bool check_async_exception); enum ProcessResult { _no_operation = 0, @@ -148,6 +152,14 @@ class HandshakeState { Thread* active_handshaker() const { return Atomic::load(&_active_handshaker); } + // Support for asynchronous exceptions + private: + bool _async_exceptions_blocked; + + bool async_exceptions_blocked() { return _async_exceptions_blocked; } + void set_async_exceptions_blocked(bool b) { _async_exceptions_blocked = b; } + void handle_unsafe_access_error(); + // Suspend/resume support private: // This flag is true when the thread owning this diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 7cbdb00995cc05263af5e785ad2df36582737787..f3d9b78998d98712830b3d530660e2fe528d4d62 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -210,7 +210,7 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition { if (SafepointMechanism::should_process(_thread, _allow_suspend)) { _pr(_thread); - SafepointMechanism::process_if_requested(_thread, _allow_suspend); + SafepointMechanism::process_if_requested(_thread, _allow_suspend, false /* check_async_exception */); } } }; diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index a6e279cfcb2ab9141bbb6e54a950863465625a1c..02f1c730c28df471a866e46100ea7df43cc1b66c 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1897,7 +1897,10 @@ int ObjectMonitor::TrySpin(JavaThread* current) { // This is in keeping with the "no loitering in runtime" rule. // We periodically check to see if there's a safepoint pending. if ((ctr & 0xFF) == 0) { - if (SafepointMechanism::should_process(current)) { + // Can't call SafepointMechanism::should_process() since that + // might update the poll values and we could be in a thread_blocked + // state here which is not allowed so just check the poll. + if (SafepointMechanism::local_poll_armed(current)) { goto Abort; // abrupt spin egress } SpinPause(); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index e8165fe7ff3c0ebecff7571bf0718cbb84027c7b..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; } @@ -658,9 +660,13 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { 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; } @@ -1167,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 @@ -1206,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/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 44240f85b71cc92bb20d9b26e9651c1e3313303d..e4b813c6a3ed49bccecd430afe86c299049f2798 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -963,33 +963,34 @@ void ThreadSafepointState::handle_polling_page_exception() { set_at_poll_safepoint(true); // Process pending operation // We never deliver an async exception at a polling point as the - // compiler may not have an exception handler for it. The polling - // code will notice the pending async exception, deoptimize and - // the exception will be delivered. (Polling at a return point - // is ok though). Sure is a lot of bother for a deprecated feature... + // compiler may not have an exception handler for it (polling at + // a return point is ok though). We will check for a pending async + // exception below and deoptimize if needed. We also cannot deoptimize + // and still install the exception here because live registers needed + // during deoptimization are clobbered by the exception path. The + // exception will just be delivered once we get into the interpreter. SafepointMechanism::process_if_requested_with_exit_check(self, false /* check asyncs */); set_at_poll_safepoint(false); - // If we have a pending async exception deoptimize the frame - // as otherwise we may never deliver it. if (self->has_async_exception_condition()) { Deoptimization::deoptimize_frame(self, caller_fr.id()); + log_info(exceptions)("deferred async exception at compiled safepoint"); } - // If an exception has been installed we must check for a pending deoptimization - // Deoptimize frame if exception has been thrown. - + // If an exception has been installed we must verify that the top frame wasn't deoptimized. if (self->has_pending_exception() ) { RegisterMap map(self, true, false); frame caller_fr = stub_fr.sender(&map); if (caller_fr.is_deoptimized_frame()) { - // The exception patch will destroy registers that are still - // live and will be needed during deoptimization. Defer the - // Async exception should have deferred the exception until the - // next safepoint which will be detected when we get into - // the interpreter so if we have an exception now things - // are messed up. - + // The exception path will destroy registers that are still + // live and will be needed during deoptimization, so if we + // have an exception now things are messed up. We only check + // at this scope because for a poll return it is ok to deoptimize + // while having a pending exception since 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). fatal("Exception installed and deoptimization is pending"); } } diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index 0a4d9a436c05871182d1686109ebfc90bdd7036e..97c232979ee368eb226ddc9e953fba75c4d5526a 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -111,7 +111,7 @@ void SafepointMechanism::update_poll_values(JavaThread* thread) { } } -void SafepointMechanism::process(JavaThread *thread, bool allow_suspend) { +void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool check_async_exception) { // Read global poll and has_handshake after local poll OrderAccess::loadload(); @@ -135,7 +135,7 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend) { // 3) Before the handshake code is run StackWatermarkSet::on_safepoint(thread); - need_rechecking = thread->handshake_state()->has_operation() && thread->handshake_state()->process_by_self(allow_suspend); + need_rechecking = thread->handshake_state()->has_operation() && thread->handshake_state()->process_by_self(allow_suspend, check_async_exception); } while (need_rechecking); update_poll_values(thread); diff --git a/src/hotspot/share/runtime/safepointMechanism.hpp b/src/hotspot/share/runtime/safepointMechanism.hpp index 46cac5e4a610fb6c91b163e187d4fd837554c43f..4479759c084e1fa09e22beda3968c26364d7cf47 100644 --- a/src/hotspot/share/runtime/safepointMechanism.hpp +++ b/src/hotspot/share/runtime/safepointMechanism.hpp @@ -49,7 +49,7 @@ class SafepointMechanism : public AllStatic { static inline bool global_poll(); - static void process(JavaThread *thread, bool allow_suspend); + static void process(JavaThread *thread, bool allow_suspend, bool check_async_exception); static void default_initialize(); @@ -80,8 +80,8 @@ class SafepointMechanism : public AllStatic { static inline bool should_process(JavaThread* thread, bool allow_suspend = true); // Processes a pending requested operation. - static inline void process_if_requested(JavaThread* thread, bool allow_suspend = true); - static inline void process_if_requested_with_exit_check(JavaThread* thread, bool check_asyncs); + static inline void process_if_requested(JavaThread* thread, bool allow_suspend, bool check_async_exception); + static inline void process_if_requested_with_exit_check(JavaThread* thread, bool check_async_exception); // Compute what the poll values should be and install them. static void update_poll_values(JavaThread* thread); diff --git a/src/hotspot/share/runtime/safepointMechanism.inline.hpp b/src/hotspot/share/runtime/safepointMechanism.inline.hpp index 9439672157f52830b715927fe3e99da184a06d0c..3cac28dca1627957be6acb7fe8b4f54ec75fbbff 100644 --- a/src/hotspot/share/runtime/safepointMechanism.inline.hpp +++ b/src/hotspot/share/runtime/safepointMechanism.inline.hpp @@ -66,19 +66,17 @@ bool SafepointMechanism::global_poll() { bool SafepointMechanism::should_process(JavaThread* thread, bool allow_suspend) { if (!local_poll_armed(thread)) { return false; - } else if (allow_suspend) { - return true; } - // We are armed but we should ignore suspend operations. + if (global_poll() || // Safepoint - thread->handshake_state()->has_a_non_suspend_operation() || // Non-suspend handshake + thread->handshake_state()->has_operation(allow_suspend, false /* check_async_exception */) || // Handshake !StackWatermarkSet::processing_started(thread)) { // StackWatermark processing is not started return true; } // It has boiled down to two possibilities: // 1: We have nothing to process, this just a disarm poll. - // 2: We have a suspend handshake, which cannot be processed. + // 2: We have a suspend or async exception handshake, which cannot be processed. // We update the poll value in case of a disarm, to reduce false positives. update_poll_values(thread); @@ -88,19 +86,19 @@ bool SafepointMechanism::should_process(JavaThread* thread, bool allow_suspend) return false; } -void SafepointMechanism::process_if_requested(JavaThread* thread, bool allow_suspend) { +void SafepointMechanism::process_if_requested(JavaThread* thread, bool allow_suspend, bool check_async_exception) { // Check NoSafepointVerifier. This also clears unhandled oops if CheckUnhandledOops is used. thread->check_possible_safepoint(); if (local_poll_armed(thread)) { - process(thread, allow_suspend); + process(thread, allow_suspend, check_async_exception); } } -void SafepointMechanism::process_if_requested_with_exit_check(JavaThread* thread, bool check_asyncs) { - process_if_requested(thread); +void SafepointMechanism::process_if_requested_with_exit_check(JavaThread* thread, bool check_async_exception) { + process_if_requested(thread, true /* allow_suspend */, check_async_exception); if (thread->has_special_runtime_exit_condition()) { - thread->handle_special_runtime_exit_condition(check_asyncs); + thread->handle_special_runtime_exit_condition(); } } 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 988d6ccfac95199f75c49cc932cbcb647eea9f7c..d6ac3dc921be860b8d001e35f107b3aa961ab07f 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -266,7 +266,7 @@ void NMethodSweeper::force_sweep() { */ void NMethodSweeper::handle_safepoint_request() { JavaThread* thread = JavaThread::current(); - if (SafepointMechanism::should_process(thread)) { + if (SafepointMechanism::local_poll_armed(thread)) { if (PrintMethodFlushing && Verbose) { tty->print_cr("### Sweep at %d out of %d, yielding to safepoint", _seen, CodeCache::nmethod_count()); } diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index d4234575fc0332b4e71fe54e48dc324d7cea42ab..b7fc180ee4496770c0242c8801a063acc1512091 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.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 @@ -452,7 +452,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread } static bool useHeavyMonitors() { -#if defined(X86) || defined(AARCH64) || defined(PPC64) +#if defined(X86) || defined(AARCH64) || defined(PPC64) || defined(RISCV64) return UseHeavyMonitors; #else return false; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 0ec50849f5a5f6936e964268cb2babd4ecd63e61..76e7e9d1e55982212f9d44ee79015e7088b06742 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: " @@ -1014,10 +1014,6 @@ JavaThread::JavaThread() : _monitor_chunks(nullptr), _suspend_flags(0), - _pending_async_exception(nullptr), -#ifdef ASSERT - _is_unsafe_access_error(false), -#endif _thread_state(_thread_new), _saved_exception_pc(nullptr), @@ -1373,23 +1369,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); @@ -1584,154 +1581,104 @@ void JavaThread::remove_monitor_chunk(MonitorChunk* chunk) { } } +void JavaThread::handle_special_runtime_exit_condition() { + if (is_obj_deopt_suspend()) { + frame_anchor()->make_walkable(this); + wait_for_object_deoptimization(); + } + JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);) +} + // Asynchronous exceptions support // -void JavaThread::check_and_handle_async_exceptions() { - if (has_last_Java_frame() && has_async_exception_condition()) { - // 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 - // 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). - - if (is_at_poll_safepoint()) { - // if the code we are returning to has deoptimized we must defer - // the exception otherwise live registers get clobbered on the - // exception path before deoptimization is able to retrieve them. - // - RegisterMap map(this, false); - frame caller_fr = last_frame().sender(&map); - assert(caller_fr.is_compiled_frame(), "what?"); - if (caller_fr.is_deoptimized_frame()) { - log_info(exceptions)("deferred async exception at compiled safepoint"); - return; +void JavaThread::handle_async_exception(oop java_throwable) { + assert(java_throwable != NULL, "should have an _async_exception to throw"); + assert(!is_at_poll_safepoint(), "should have never called this method"); + + if (has_last_Java_frame()) { + frame f = last_frame(); + if (f.is_runtime_frame()) { + // If the topmost frame is a runtime stub, then we are calling into + // OptoRuntime from compiled code. Some runtime stubs (new, monitor_exit..) + // must deoptimize the caller before continuing, as the compiled exception + // handler table may not be valid. + RegisterMap reg_map(this, false); + frame compiled_frame = f.sender(®_map); + if (!StressCompiledExceptionHandlers && compiled_frame.can_be_deoptimized()) { + Deoptimization::deoptimize(this, compiled_frame); } } } - if (!clear_async_exception_condition()) { - return; - } - - if (_pending_async_exception != NULL) { - // Only overwrite an already pending exception if it is not a threadDeath. - if (!has_pending_exception() || !pending_exception()->is_a(vmClasses::ThreadDeath_klass())) { + // Only overwrite an already pending exception if it is not a ThreadDeath. + if (!has_pending_exception() || !pending_exception()->is_a(vmClasses::ThreadDeath_klass())) { - // We cannot call Exceptions::_throw(...) here because we cannot block - set_pending_exception(_pending_async_exception, __FILE__, __LINE__); + // We cannot call Exceptions::_throw(...) here because we cannot block + set_pending_exception(java_throwable, __FILE__, __LINE__); - LogTarget(Info, exceptions) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this)); - if (has_last_Java_frame()) { - frame f = last_frame(); - ls.print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp())); - } - ls.print_cr(" of type: %s", _pending_async_exception->klass()->external_name()); + LogTarget(Info, exceptions) lt; + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this)); + if (has_last_Java_frame()) { + frame f = last_frame(); + ls.print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp())); } + ls.print_cr(" of type: %s", java_throwable->klass()->external_name()); } - // Always null out the _pending_async_exception oop here since the async condition was - // already cleared above and thus considered handled. - _pending_async_exception = NULL; - } else { - assert(_is_unsafe_access_error, "must be"); - DEBUG_ONLY(_is_unsafe_access_error = false); - - // We may be at method entry which requires we save the do-not-unlock flag. - UnlockFlagSaver fs(this); - Exceptions::throw_unsafe_access_internal_error(this, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation"); - // We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending - // suspend requests and object reallocation operations if any since we might be going to Java after this. - SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */); } } -void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) { +void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) { + // Do not throw asynchronous exceptions against the compiler thread. + if (!can_call_java()) { + delete aeh; + return; + } - if (is_obj_deopt_suspend()) { - frame_anchor()->make_walkable(this); - wait_for_object_deoptimization(); + // Don't install a new pending async exception if there is already + // a pending ThreadDeath one. Just interrupt thread from potential + // wait()/sleep()/park() and return. + if (has_async_exception_condition(true /* ThreadDeath_only */)) { + java_lang_Thread::set_interrupted(threadObj(), true); + this->interrupt(); + delete aeh; + return; } - // We might be here for reasons in addition to the self-suspend request - // so check for other async requests. - if (check_asyncs) { - check_and_handle_async_exceptions(); + oop exception = aeh->exception(); + Handshake::execute(aeh, this); // Install asynchronous handshake + + ResourceMark rm; + if (log_is_enabled(Info, exceptions)) { + log_info(exceptions)("Pending Async. exception installed of type: %s", + InstanceKlass::cast(exception->klass())->external_name()); } + // for AbortVMOnException flag + Exceptions::debug_check_abort(exception->klass()->external_name()); - JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);) + // Interrupt thread so it will wake up from a potential wait()/sleep()/park() + java_lang_Thread::set_interrupted(threadObj(), true); + this->interrupt(); } -class InstallAsyncExceptionClosure : public HandshakeClosure { - Handle _throwable; // The Throwable thrown at the target Thread +class InstallAsyncExceptionHandshake : public HandshakeClosure { + AsyncExceptionHandshake* _aeh; public: - InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {} - + InstallAsyncExceptionHandshake(AsyncExceptionHandshake* aeh) : + HandshakeClosure("InstallAsyncException"), _aeh(aeh) {} void do_thread(Thread* thr) { JavaThread* target = JavaThread::cast(thr); - // Note that this now allows multiple ThreadDeath exceptions to be - // thrown at a thread. - // The target thread has run and has not exited yet. - target->send_thread_stop(_throwable()); + target->install_async_exception(_aeh); } }; void JavaThread::send_async_exception(JavaThread* target, oop java_throwable) { - Handle throwable(Thread::current(), java_throwable); - InstallAsyncExceptionClosure vm_stop(throwable); - Handshake::execute(&vm_stop, target); -} - -void JavaThread::send_thread_stop(oop java_throwable) { - ResourceMark rm; - assert(is_handshake_safe_for(Thread::current()), - "should be self or handshakee"); - - // Do not throw asynchronous exceptions against the compiler thread - // (the compiler thread should not be a Java thread -- fix in 1.4.2) - if (!can_call_java()) return; - - { - // Actually throw the Throwable against the target Thread - however - // only if there is no thread death exception installed already. - if (_pending_async_exception == NULL || !_pending_async_exception->is_a(vmClasses::ThreadDeath_klass())) { - // If the topmost frame is a runtime stub, then we are calling into - // OptoRuntime from compiled code. Some runtime stubs (new, monitor_exit..) - // must deoptimize the caller before continuing, as the compiled exception handler table - // may not be valid - if (has_last_Java_frame()) { - frame f = last_frame(); - if (f.is_runtime_frame() || f.is_safepoint_blob_frame()) { - RegisterMap reg_map(this, false); - frame compiled_frame = f.sender(®_map); - if (!StressCompiledExceptionHandlers && compiled_frame.can_be_deoptimized()) { - Deoptimization::deoptimize(this, compiled_frame); - } - } - } - - // Set async. pending exception in thread. - set_pending_async_exception(java_throwable); - - if (log_is_enabled(Info, exceptions)) { - ResourceMark rm; - log_info(exceptions)("Pending Async. exception installed of type: %s", - InstanceKlass::cast(_pending_async_exception->klass())->external_name()); - } - // for AbortVMOnException flag - Exceptions::debug_check_abort(_pending_async_exception->klass()->external_name()); - } - } - - - // Interrupt thread so it will wake up from a potential wait()/sleep()/park() - java_lang_Thread::set_interrupted(threadObj(), true); - this->interrupt(); + OopHandle e(Universe::vm_global(), java_throwable); + InstallAsyncExceptionHandshake iaeh(new AsyncExceptionHandshake(e)); + Handshake::execute(&iaeh, target); } @@ -1962,7 +1909,6 @@ void JavaThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) { // around using this function f->do_oop((oop*) &_vm_result); f->do_oop((oop*) &_exception_oop); - f->do_oop((oop*) &_pending_async_exception); #if INCLUDE_JVMCI f->do_oop((oop*) &_jvmci_reserved_oop0); #endif diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 0d56f3dc68200789518ea448369a461ab609f7a8..86bc9df6ffaf92dc8c6e904b5032431f67930d05 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -68,6 +68,7 @@ class OSThread; class ThreadStatistics; class ConcurrentLocksDump; class MonitorInfo; +class AsyncExceptionHandshake; class vframeArray; class vframe; @@ -785,13 +786,11 @@ 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 }; // various suspension related flags - atomically updated - // overloaded with async exceptions so that we do a single check when transitioning from native->Java volatile uint32_t _suspend_flags; inline void set_suspend_flag(SuspendFlags f); @@ -805,23 +804,25 @@ class JavaThread: public Thread { bool is_trace_suspend() { return (_suspend_flags & _trace_flag) != 0; } bool is_obj_deopt_suspend() { return (_suspend_flags & _obj_deopt) != 0; } - // Asynchronous exceptions support + // Asynchronous exception support private: - oop _pending_async_exception; -#ifdef ASSERT - bool _is_unsafe_access_error; -#endif + friend class InstallAsyncExceptionHandshake; + friend class AsyncExceptionHandshake; + friend class HandshakeState; - inline bool clear_async_exception_condition(); + void install_async_exception(AsyncExceptionHandshake* aec = NULL); + void handle_async_exception(oop java_throwable); public: - bool has_async_exception_condition() { - return (_suspend_flags & _has_async_exception) != 0; - } - inline void set_pending_async_exception(oop e); + bool has_async_exception_condition(bool ThreadDeath_only = false); inline void set_pending_unsafe_access_error(); static void send_async_exception(JavaThread* jt, oop java_throwable); - 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() @@ -1160,13 +1161,10 @@ class JavaThread: public Thread { // current thread, i.e. reverts optimizations based on escape analysis. void wait_for_object_deoptimization(); - // these next two are also used for self-suspension and async exception support - void handle_special_runtime_exit_condition(bool check_asyncs = true); - - // Return true if JavaThread has an asynchronous condition or - // if external suspension is requested. + // Support for object deoptimization and JFR suspension + void handle_special_runtime_exit_condition(); bool has_special_runtime_exit_condition() { - return (_suspend_flags & (_has_async_exception | _obj_deopt JFR_ONLY(| _trace_flag))) != 0; + return (_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0; } // Fast-locking support diff --git a/src/hotspot/share/runtime/thread.inline.hpp b/src/hotspot/share/runtime/thread.inline.hpp index 7d27a3bf257cacbeb075f15dac7e60611108ac35..61aa7cca87b9e22ea6d5bdcc6ed3ff4b200b160f 100644 --- a/src/hotspot/share/runtime/thread.inline.hpp +++ b/src/hotspot/share/runtime/thread.inline.hpp @@ -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. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,7 +28,11 @@ #include "runtime/thread.hpp" +#include "classfile/vmClasses.hpp" #include "gc/shared/tlab_globals.hpp" +#include "memory/universe.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/oopHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/nonJavaThread.hpp" #include "runtime/orderAccess.hpp" @@ -122,24 +126,66 @@ inline void JavaThread::clear_obj_deopt_flag() { clear_suspend_flag(_obj_deopt); } -inline bool JavaThread::clear_async_exception_condition() { - bool ret = has_async_exception_condition(); - clear_suspend_flag(_has_async_exception); - return ret; +class AsyncExceptionHandshake : public AsyncHandshakeClosure { + OopHandle _exception; + bool _is_ThreadDeath; + public: + AsyncExceptionHandshake(OopHandle& o, const char* name = "AsyncExceptionHandshake") + : AsyncHandshakeClosure(name), _exception(o) { + _is_ThreadDeath = exception()->is_a(vmClasses::ThreadDeath_klass()); + } + + ~AsyncExceptionHandshake() { + assert(!_exception.is_empty(), "invariant"); + _exception.release(Universe::vm_global()); + } + + void do_thread(Thread* thr) { + JavaThread* self = JavaThread::cast(thr); + assert(self == JavaThread::current(), "must be"); + + self->handle_async_exception(exception()); + } + oop exception() { + assert(!_exception.is_empty(), "invariant"); + return _exception.resolve(); + } + bool is_async_exception() { return true; } + bool is_ThreadDeath() { return _is_ThreadDeath; } +}; + +class UnsafeAccessErrorHandshake : public AsyncHandshakeClosure { + public: + UnsafeAccessErrorHandshake() : AsyncHandshakeClosure("UnsafeAccessErrorHandshake") {} + void do_thread(Thread* thr) { + JavaThread* self = JavaThread::cast(thr); + assert(self == JavaThread::current(), "must be"); + + self->handshake_state()->handle_unsafe_access_error(); + } + bool is_async_exception() { return true; } +}; + +inline void JavaThread::set_pending_unsafe_access_error() { + if (!has_async_exception_condition()) { + Handshake::execute(new UnsafeAccessErrorHandshake(), this); + } } -inline void JavaThread::set_pending_async_exception(oop e) { - _pending_async_exception = e; - set_suspend_flag(_has_async_exception); +inline bool JavaThread::has_async_exception_condition(bool ThreadDeath_only) { + return handshake_state()->has_async_exception_operation(ThreadDeath_only); } -inline void JavaThread::set_pending_unsafe_access_error() { - set_suspend_flag(_has_async_exception); - DEBUG_ONLY(_is_unsafe_access_error = true); +inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) { + assert(!_target->handshake_state()->async_exceptions_blocked(), "Nesting is not supported"); + _target->handshake_state()->set_async_exceptions_blocked(true); +} +inline JavaThread::NoAsyncExceptionDeliveryMark::~NoAsyncExceptionDeliveryMark() { + _target->handshake_state()->set_async_exceptions_blocked(false); } inline JavaThreadState JavaThread::thread_state() const { -#if defined(PPC64) || defined (AARCH64) +#if defined(PPC64) || defined (AARCH64) || defined(RISCV64) // Use membars when accessing volatile _thread_state. See // Threads::create_vm() for size checks. return (JavaThreadState) Atomic::load_acquire((volatile jint*)&_thread_state); @@ -151,7 +197,7 @@ inline JavaThreadState JavaThread::thread_state() const { inline void JavaThread::set_thread_state(JavaThreadState s) { assert(current_or_null() == NULL || current_or_null() == this, "state change should only be called by the current thread"); -#if defined(PPC64) || defined (AARCH64) +#if defined(PPC64) || defined (AARCH64) || defined(RISCV64) // Use membars when accessing volatile _thread_state. See // Threads::create_vm() for size checks. Atomic::release_store((volatile jint*)&_thread_state, (jint)s); 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/runtime/vmOperations.hpp b/src/hotspot/share/runtime/vmOperations.hpp index 262ac740c1c0fbe683c7de0a89b14c3040492fee..557f4bc3171a9ae58c04ed57175db0c220550645 100644 --- a/src/hotspot/share/runtime/vmOperations.hpp +++ b/src/hotspot/share/runtime/vmOperations.hpp @@ -115,8 +115,6 @@ class VM_DeoptimizeFrame: public VM_Operation { #ifndef PRODUCT class VM_DeoptimizeAll: public VM_Operation { - private: - Klass* _dependee; public: VM_DeoptimizeAll() {} VMOp_Type type() const { return VMOp_DeoptimizeAll; } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index bebae07e5fb8bf95f9da7b3abae9660440ca2b64..940fc3e3eafab75d6691d352737a82f20d04892f 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -716,7 +716,6 @@ nonstatic_field(JavaThread, _current_pending_monitor_is_from_java, bool) \ volatile_nonstatic_field(JavaThread, _current_waiting_monitor, ObjectMonitor*) \ volatile_nonstatic_field(JavaThread, _suspend_flags, uint32_t) \ - nonstatic_field(JavaThread, _pending_async_exception, oop) \ volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ volatile_nonstatic_field(JavaThread, _exception_pc, address) \ volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \ @@ -1757,9 +1756,11 @@ declare_c2_type(MulVFNode, VectorNode) \ declare_c2_type(MulReductionVFNode, ReductionNode) \ declare_c2_type(MulVDNode, VectorNode) \ - declare_c2_type(NegVINode, VectorNode) \ - declare_c2_type(NegVFNode, VectorNode) \ - declare_c2_type(NegVDNode, VectorNode) \ + declare_c2_type(NegVNode, VectorNode) \ + declare_c2_type(NegVINode, NegVNode) \ + declare_c2_type(NegVLNode, NegVNode) \ + declare_c2_type(NegVFNode, NegVNode) \ + declare_c2_type(NegVDNode, NegVNode) \ declare_c2_type(FmaVDNode, VectorNode) \ declare_c2_type(FmaVFNode, VectorNode) \ declare_c2_type(CMoveVFNode, VectorNode) \ @@ -2119,12 +2120,6 @@ declare_constant(JVM_CONSTANT_DynamicInError) \ declare_constant(JVM_CONSTANT_InternalMax) \ \ - /*****************************/ \ - /* Thread::SuspendFlags enum */ \ - /*****************************/ \ - \ - declare_constant(JavaThread::_has_async_exception) \ - \ /*******************/ \ /* JavaThreadState */ \ /*******************/ \ diff --git a/src/hotspot/share/services/attachListener.cpp b/src/hotspot/share/services/attachListener.cpp index f916f43849ffb567eafbfe0fcdf581dd898b7216..a376de6c24633f61a17080ccf240cfc1884e7cfa 100644 --- a/src/hotspot/share/services/attachListener.cpp +++ b/src/hotspot/share/services/attachListener.cpp @@ -81,7 +81,7 @@ static jint get_properties(AttachOperation* op, outputStream* out, Symbol* seria JavaCallArguments args; - Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); + Symbol* signature = vmSymbols::void_byte_array_signature(); JavaCalls::call_static(&result, k, serializePropertiesMethod, diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 06b9539a94d7dc2533d8fac8ca67ec3cefd04a1e..ab4eb41f8c1261dd6aa9a53c38f1b8d7648040b1 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -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 @@ -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)); @@ -356,7 +358,7 @@ void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) { JavaValue result(T_OBJECT); JavaCallArguments args; - Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); + Symbol* signature = vmSymbols::void_byte_array_signature(); JavaCalls::call_static(&result, ik, vmSymbols::serializePropertiesToByteArray_name(), @@ -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/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index 4ddc8e18ae6620bab8d8a8108f04a2585a3e14c5..15149d1be7e3ac8fe13fcc90d121c3d4a1c3631f 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -250,12 +250,6 @@ void Exceptions::throw_stack_overflow_exception(JavaThread* THREAD, const char* _throw(THREAD, file, line, exception); } -void Exceptions::throw_unsafe_access_internal_error(JavaThread* thread, const char* file, int line, const char* message) { - Handle h_exception = new_exception(thread, vmSymbols::java_lang_InternalError(), message); - java_lang_InternalError::set_during_unsafe_access(h_exception()); - _throw(thread, file, line, h_exception, message); -} - void Exceptions::fthrow(JavaThread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) { const int max_msg_size = 1024; va_list ap; @@ -538,7 +532,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 a599682e25bf234788a715feb9f1a443d72efdf8..9103dc0ffed9c767edc68a94fcc7706489fc46dc 100644 --- a/src/hotspot/share/utilities/exceptions.hpp +++ b/src/hotspot/share/utilities/exceptions.hpp @@ -173,8 +173,6 @@ class Exceptions { static void throw_stack_overflow_exception(JavaThread* thread, const char* file, int line, const methodHandle& method); - static void throw_unsafe_access_internal_error(JavaThread* thread, const char* file, int line, const char* message); - static void wrap_dynamic_exception(bool is_indy, JavaThread* thread); // Exception counting for error files of interesting exceptions that may have 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 8dea1a754faa2166fcd78870782ffb2155c7aa69..bf647fbf65bfde96e47437d44622ff7e659eb984 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -545,6 +545,32 @@ #define MACOS_AARCH64_ONLY(x) MACOS_ONLY(AARCH64_ONLY(x)) +#if defined(RISCV32) || defined(RISCV64) +#define RISCV +#define RISCV_ONLY(code) code +#define NOT_RISCV(code) +#else +#undef RISCV +#define RISCV_ONLY(code) +#define NOT_RISCV(code) code +#endif + +#ifdef RISCV32 +#define RISCV32_ONLY(code) code +#define NOT_RISCV32(code) +#else +#define RISCV32_ONLY(code) +#define NOT_RISCV32(code) code +#endif + +#ifdef RISCV64 +#define RISCV64_ONLY(code) code +#define NOT_RISCV64(code) +#else +#define RISCV64_ONLY(code) +#define NOT_RISCV64(code) code +#endif + #ifdef VM_LITTLE_ENDIAN #define LITTLE_ENDIAN_ONLY(code) code #define BIG_ENDIAN_ONLY(code) diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index efb6a4ac7e6b77a51a03eb58f79428b9aa199ed1..52a1c5f0a145b020fb09bb25a32a631e3d69726f 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -746,7 +746,7 @@ void defaultStream::start_log() { outputStream *text = xs->text(); for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { assert(p->key() != NULL, "p->key() is NULL"); - if (p->is_readable()) { + if (p->readable()) { // Print in two stages to avoid problems with long // keys/values. text->print_raw(p->key()); 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/AESKeyGenerator.java b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java index 6ca4d929acba8983fe4b8e59cf515970987d0f9d..2672807aaddaeb976740dcfa446c1dd559b87adf 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.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 @@ -34,7 +34,7 @@ import java.util.Arrays; import javax.crypto.KeyGeneratorSpi; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; - +import sun.security.util.SecurityProviderConstants; /** * This class generates a AES key. @@ -46,7 +46,8 @@ import javax.crypto.spec.SecretKeySpec; public final class AESKeyGenerator extends KeyGeneratorSpi { private SecureRandom random = null; - private int keySize = 16; // default keysize (in number of bytes) + // default keysize (in number of bytes) + private int keySize = SecurityProviderConstants.getDefAESKeySize() >> 3; /** * Empty constructor. 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/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/ObjectInput.java b/src/java.base/share/classes/java/io/ObjectInput.java index fe80b377a0d5976b1fd953a618f5f3e6fed4e5d8..941b5f03498280077f5b591f79f3be45660cf930 100644 --- a/src/java.base/share/classes/java/io/ObjectInput.java +++ b/src/java.base/share/classes/java/io/ObjectInput.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 @@ -62,8 +62,9 @@ public interface ObjectInput extends DataInput, AutoCloseable { * Reads into an array of bytes. This method will * block until some input is available. * @param b the buffer into which the data is read - * @return the actual number of bytes read, -1 is - * returned when the end of the stream is reached. + * @return the total number of bytes read into the buffer, or + * {@code -1} if there is no more data because the end of + * the stream has been reached. * @throws IOException If an I/O error has occurred. */ public int read(byte[] b) throws IOException; @@ -74,8 +75,9 @@ public interface ObjectInput extends DataInput, AutoCloseable { * @param b the buffer into which the data is read * @param off the start offset of the data * @param len the maximum number of bytes read - * @return the actual number of bytes read, -1 is - * returned when the end of the stream is reached. + * @return the total number of bytes read into the buffer, or + * {@code -1} if there is no more data because the end of + * the stream has been reached. * @throws IOException If an I/O error has occurred. */ public int read(byte[] b, int off, int len) throws IOException; diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 714785cd117bf67ce0d057dfabdebbdb04152a00..319981e864b0e5702d9aec984a399187ce0e9df4 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1031,8 +1031,9 @@ public class ObjectInputStream * @param buf the buffer into which the data is read * @param off the start offset in the destination array {@code buf} * @param len the maximum number of bytes read - * @return the actual number of bytes read, -1 is returned when the end of - * the stream is reached. + * @return the total number of bytes read into the buffer, or + * {@code -1} if there is no more data because the end of + * the stream has been reached. * @throws NullPointerException if {@code buf} is {@code null}. * @throws IndexOutOfBoundsException if {@code off} is negative, * {@code len} is negative, or {@code len} is greater than @@ -1429,9 +1430,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 +1995,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 +2011,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 +2043,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 +2214,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 +2254,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 +2379,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..9a3f96d07852c0a2c697cfeb72c15eda059fbc75 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 @@ -80,7 +80,7 @@ import static java.io.ObjectStreamField.*; * Java Object Serialization Specification, Section 4, "Class Descriptors" * @since 1.1 */ -public class ObjectStreamClass implements Serializable { +public final class ObjectStreamClass implements Serializable { /** serialPersistentFields value indicating no serializable fields */ public static final ObjectStreamField[] NO_FIELDS = @@ -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/SequenceInputStream.java b/src/java.base/share/classes/java/io/SequenceInputStream.java index 5f692ce6c44de3f855d944dccd688ad403069fd2..b4f948902a2a7e8b58f5de3ff4ecdfc56e5bf327 100644 --- a/src/java.base/share/classes/java/io/SequenceInputStream.java +++ b/src/java.base/share/classes/java/io/SequenceInputStream.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 @@ -177,7 +177,9 @@ public class SequenceInputStream extends InputStream { * @param off the start offset in array {@code b} * at which the data is written. * @param len the maximum number of bytes read. - * @return int the number of bytes read. + * @return the total number of bytes read into the buffer, or + * {@code -1} if there is no more data because the end of + * the last contained stream has been reached. * @throws NullPointerException If {@code b} is {@code null}. * @throws IndexOutOfBoundsException If {@code off} is negative, * {@code len} is negative, or {@code len} is 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..b05ad6fa9ed70db66a59394db1bd057644eba52e 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. */ @@ -67,6 +68,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ byte coder; + /** + * The attribute indicates {@code value} might be compressible to LATIN1 if it is UTF16-encoded. + * An inflated byte array becomes compressible only when those non-latin1 chars are deleted. + * We simply set this attribute in all methods which may delete chars. Therefore, there are + * false positives. Subclasses and String need to handle it properly. + */ + boolean maybeLatin1; + /** * The count is the number of characters used. */ @@ -131,10 +140,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { final byte initCoder; if (COMPACT_STRINGS) { - if (seq instanceof AbstractStringBuilder) { - initCoder = ((AbstractStringBuilder)seq).getCoder(); - } else if (seq instanceof String) { - initCoder = ((String)seq).coder(); + if (seq instanceof AbstractStringBuilder asb) { + initCoder = asb.getCoder(); + maybeLatin1 |= asb.maybeLatin1; + } else if (seq instanceof String s) { + initCoder = s.coder(); } else { initCoder = LATIN1; } @@ -318,6 +328,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { } else { StringUTF16.fillNull(value, count, newLength); } + } else if (count > newLength) { + maybeLatin1 = true; } count = newLength; } @@ -527,6 +539,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { inflate(); } StringUTF16.putCharSB(value, index, ch); + maybeLatin1 = true; } } @@ -596,6 +609,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { inflateIfNeededFor(asb); asb.getBytes(value, count, coder); count += len; + maybeLatin1 |= asb.maybeLatin1; return this; } @@ -906,6 +920,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (len > 0) { shift(end, -len); this.count = count - len; + maybeLatin1 = true; } return this; } @@ -957,6 +972,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { checkIndex(index, count); shift(index + 1, -1); count--; + maybeLatin1 = true; return this; } @@ -991,6 +1007,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { shift(end, newCount - count); this.count = newCount; putStringAt(start, str); + maybeLatin1 = true; return this; } 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..4155e8616f5bd191c51dc8c7e57b537f2a0fb1be 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 @@ -740,6 +753,7 @@ public final class Math { * @see java.lang.Integer#MAX_VALUE * @see java.lang.Integer#MIN_VALUE */ + @IntrinsicCandidate public static int round(float a) { int intBits = Float.floatToRawIntBits(a); int biasedExp = (intBits & FloatConsts.EXP_BIT_MASK) @@ -789,6 +803,7 @@ public final class Math { * @see java.lang.Long#MAX_VALUE * @see java.lang.Long#MIN_VALUE */ + @IntrinsicCandidate public static long round(double a) { long longBits = Double.doubleToRawLongBits(a); long biasedExp = (longBits & DoubleConsts.EXP_BIT_MASK) diff --git a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index dad94430fda79bc43a02b39f14466ac88df49c13..ff9cf8b0fbd9b2bf7f3f21841f1e1b304d85f034 100644 --- a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.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 @@ -24,6 +24,8 @@ */ package java.lang; +import jdk.internal.misc.InnocuousThread; + import java.lang.annotation.Native; import java.security.AccessController; import java.security.PrivilegedAction; @@ -89,10 +91,6 @@ final class ProcessHandleImpl implements ProcessHandle { // of the processReaper threads. ThreadLocalRandom.current(); - ThreadGroup tg = Thread.currentThread().getThreadGroup(); - while (tg.getParent() != null) tg = tg.getParent(); - ThreadGroup systemThreadGroup = tg; - // For a debug build, the stack shadow zone is larger; // Increase the total stack size to avoid potential stack overflow. int debugDelta = "release".equals(System.getProperty("jdk.debug")) ? 0 : (4*4096); @@ -100,11 +98,9 @@ final class ProcessHandleImpl implements ProcessHandle { ? 0 : REAPER_DEFAULT_STACKSIZE + debugDelta; ThreadFactory threadFactory = grimReaper -> { - Thread t = new Thread(systemThreadGroup, grimReaper, - "process reaper", stackSize, false); + Thread t = InnocuousThread.newSystemThread("process reaper", grimReaper, + stackSize, Thread.MAX_PRIORITY); t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); return t; }; @@ -144,33 +140,40 @@ final class ProcessHandleImpl implements ProcessHandle { processReaperExecutor.execute(new Runnable() { // Use inner class to avoid lambda stack overhead public void run() { - int exitValue = waitForProcessExit0(pid, shouldReap); - if (exitValue == NOT_A_CHILD) { - // pid not alive or not a child of this process - // If it is alive wait for it to terminate - long sleep = 300; // initial milliseconds to sleep - int incr = 30; // increment to the sleep time - - long startTime = isAlive0(pid); - long origStart = startTime; - while (startTime >= 0) { - try { - Thread.sleep(Math.min(sleep, 5000L)); // no more than 5 sec - sleep += incr; - } catch (InterruptedException ie) { - // ignore and retry - } - startTime = isAlive0(pid); // recheck if it is alive - if (startTime > 0 && origStart > 0 && startTime != origStart) { - // start time changed (and is not zero), pid is not the same process - break; + String threadName = Thread.currentThread().getName(); + Thread.currentThread().setName("process reaper (pid " + pid + ")"); + try { + int exitValue = waitForProcessExit0(pid, shouldReap); + if (exitValue == NOT_A_CHILD) { + // pid not alive or not a child of this process + // If it is alive wait for it to terminate + long sleep = 300; // initial milliseconds to sleep + int incr = 30; // increment to the sleep time + + long startTime = isAlive0(pid); + long origStart = startTime; + while (startTime >= 0) { + try { + Thread.sleep(Math.min(sleep, 5000L)); // no more than 5 sec + sleep += incr; + } catch (InterruptedException ie) { + // ignore and retry + } + startTime = isAlive0(pid); // recheck if it is alive + if (startTime > 0 && origStart > 0 && startTime != origStart) { + // start time changed (and is not zero), pid is not the same process + break; + } } + exitValue = 0; } - exitValue = 0; + newCompletion.complete(exitValue); + // remove from cache afterwards + completions.remove(pid, newCompletion); + } finally { + // Restore thread name + Thread.currentThread().setName(threadName); } - newCompletion.complete(exitValue); - // remove from cache afterwards - completions.remove(pid, newCompletion); } }); } 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..d13cf25b06698b64b7c9e1f368eed9012a7d9f9e 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) { @@ -4511,7 +4521,8 @@ public final class String this.coder = LATIN1; this.value = Arrays.copyOfRange(val, 0, length); } else { - if (COMPACT_STRINGS) { + // only try to compress val if some characters were deleted. + if (COMPACT_STRINGS && asb.maybeLatin1) { byte[] buf = StringUTF16.compress(val, 0, length); if (buf != null) { this.coder = LATIN1; diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index 1ba12bd29bc2b798dcabebf537d28a8cbe8ca612..b0ee2a5c2e3dcb01867a6eb44ce5bc041ec9c4d5 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -712,9 +712,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; @IntrinsicCandidate public synchronized String toString() { if (toStringCache == null) { - return toStringCache = - isLatin1() ? StringLatin1.newString(value, 0, count) - : StringUTF16.newString(value, 0, count); + return toStringCache = new String(this, null); } return new String(toStringCache); } diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java index 8e759c213a9a80ae8631107feb6958c5fcf66bcb..17fd105ad3fd099aece1f9dc96db265c28ff7773 100644 --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -450,8 +450,7 @@ public final class StringBuilder @IntrinsicCandidate public String toString() { // Create a copy, don't share the array - return isLatin1() ? StringLatin1.newString(value, 0, count) - : StringUTF16.newString(value, 0, count); + return new String(this); } /** 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/BoundMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index 9a4393eea276eb31db4084e840275afe725f40f9..bb15f3cfbf3a210912a0fc47342af20a7889cf4c 100644 --- a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.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 @@ -49,7 +49,7 @@ import static java.lang.invoke.MethodHandleStatics.uncaughtException; * All bound arguments are encapsulated in dedicated species. */ /*non-public*/ -abstract class BoundMethodHandle extends MethodHandle { +abstract non-sealed class BoundMethodHandle extends MethodHandle { /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) { 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/DelegatingMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java index 458810f3c107a84a6762e4d87ec0a79438f1ca46..d3986a38dab786e0b825b2aa6b5cadd4b99efd75 100644 --- a/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,11 @@ import static java.lang.invoke.MethodHandleStatics.*; * @author jrose */ /*non-public*/ -abstract class DelegatingMethodHandle extends MethodHandle { +abstract sealed class DelegatingMethodHandle extends MethodHandle + permits MethodHandleImpl.AsVarargsCollector, + MethodHandleImpl.WrappedMember, + MethodHandleImpl.IntrinsicMethodHandle, + MethodHandleImpl.CountingWrapper { protected DelegatingMethodHandle(MethodHandle target) { this(target.type(), target); } diff --git a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index d760e6e64c0dd4dee4bad8650a059ea62070b4cd..b8e1b48587b57af21a381af133e63b4eeccbfc5e 100644 --- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, 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 @@ -49,7 +49,7 @@ import static java.lang.invoke.MethodTypeForm.*; * to a class member. * @author jrose */ -class DirectMethodHandle extends MethodHandle { +sealed class DirectMethodHandle extends MethodHandle { final MemberName member; final boolean crackable; @@ -395,7 +395,7 @@ class DirectMethodHandle extends MethodHandle { } /** This subclass represents invokespecial instructions. */ - static class Special extends DirectMethodHandle { + static final class Special extends DirectMethodHandle { private final Class caller; private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class caller) { super(mtype, form, member, crackable); @@ -416,16 +416,21 @@ class DirectMethodHandle extends MethodHandle { } Object checkReceiver(Object recv) { if (!caller.isInstance(recv)) { - String msg = String.format("Receiver class %s is not a subclass of caller class %s", - recv.getClass().getName(), caller.getName()); - throw new IncompatibleClassChangeError(msg); + if (recv != null) { + String msg = String.format("Receiver class %s is not a subclass of caller class %s", + recv.getClass().getName(), caller.getName()); + throw new IncompatibleClassChangeError(msg); + } else { + String msg = String.format("Cannot invoke %s with null receiver", member); + throw new NullPointerException(msg); + } } return recv; } } /** This subclass represents invokeinterface instructions. */ - static class Interface extends DirectMethodHandle { + static final class Interface extends DirectMethodHandle { private final Class refc; private Interface(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class refc) { super(mtype, form, member, crackable); @@ -444,9 +449,14 @@ class DirectMethodHandle extends MethodHandle { @Override Object checkReceiver(Object recv) { if (!refc.isInstance(recv)) { - String msg = String.format("Receiver class %s does not implement the requested interface %s", - recv.getClass().getName(), refc.getName()); - throw new IncompatibleClassChangeError(msg); + if (recv != null) { + String msg = String.format("Receiver class %s does not implement the requested interface %s", + recv.getClass().getName(), refc.getName()); + throw new IncompatibleClassChangeError(msg); + } else { + String msg = String.format("Cannot invoke %s with null receiver", member); + throw new NullPointerException(msg); + } } return recv; } @@ -458,7 +468,7 @@ class DirectMethodHandle extends MethodHandle { } /** This subclass handles constructor references. */ - static class Constructor extends DirectMethodHandle { + static final class Constructor extends DirectMethodHandle { final MemberName initMethod; final Class instanceClass; @@ -493,7 +503,7 @@ class DirectMethodHandle extends MethodHandle { } /** This subclass handles non-static field references. */ - static class Accessor extends DirectMethodHandle { + static final class Accessor extends DirectMethodHandle { final Class fieldType; final int fieldOffset; private Accessor(MethodType mtype, LambdaForm form, MemberName member, @@ -539,7 +549,7 @@ class DirectMethodHandle extends MethodHandle { } /** This subclass handles static field references. */ - static class StaticAccessor extends DirectMethodHandle { + static final class StaticAccessor extends DirectMethodHandle { private final Class fieldType; private final Object staticBase; private final long staticOffset; diff --git a/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java b/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java index 23b7284b31183448418c5e6ad965d92e7c6354fe..cad49e2c7db610bbad8976fc76248198b58ce7b8 100644 --- a/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.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 @@ -42,7 +42,7 @@ import java.util.function.BiFunction; * (using the method handle combinator API) and then repackaging the adapted method handles into a new, indirect * var handle. */ -/* package */ class IndirectVarHandle extends VarHandle { +/* package */ final class IndirectVarHandle extends VarHandle { @Stable private final MethodHandle[] handleMap = new MethodHandle[AccessMode.COUNT]; diff --git a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java index 7703c997fc3393788f444a02c04e330f223dbd5e..6fbb7108eb7a50149d245dceb9a1c6ef70ef653a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java +++ b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.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,15 @@ package java.lang.invoke; /** * Base class for memory access var handle implementations. */ -abstract class MemoryAccessVarHandleBase extends VarHandle { +abstract sealed class MemoryAccessVarHandleBase extends VarHandle permits + MemoryAccessVarHandleByteHelper, + MemoryAccessVarHandleCharHelper, + MemoryAccessVarHandleDoubleHelper, + MemoryAccessVarHandleFloatHelper, + MemoryAccessVarHandleIntHelper, + MemoryAccessVarHandleLongHelper, + MemoryAccessVarHandleShortHelper +{ /** endianness **/ final boolean be; 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..812f26f58cc16096f82e4f655d14e861a78e841e 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 @@ -440,7 +440,9 @@ mh.invokeExact(System.out, "Hello, world."); * @author John Rose, JSR 292 EG * @since 1.7 */ -public abstract class MethodHandle implements Constable { +public abstract sealed class MethodHandle implements Constable + permits NativeMethodHandle, DirectMethodHandle, + DelegatingMethodHandle, BoundMethodHandle { /** * Internal marker interface which distinguishes (to the Java compiler) @@ -807,15 +809,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/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index 404782c047e2ae418d95bc2128022bc1b2748e1a..27176314b25d9a2498b981876c36ed0379e3ff59 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -448,10 +448,10 @@ abstract class MethodHandleImpl { return new AsVarargsCollector(target, arrayType); } - private static final class AsVarargsCollector extends DelegatingMethodHandle { + static final class AsVarargsCollector extends DelegatingMethodHandle { private final MethodHandle target; private final Class arrayType; - private @Stable MethodHandle asCollectorCache; + private MethodHandle asCollectorCache; AsVarargsCollector(MethodHandle target, Class arrayType) { this(target.type(), target, arrayType); @@ -705,7 +705,7 @@ abstract class MethodHandleImpl { * Behavior in counting and non-counting states is determined by lambda forms produced by * countingFormProducer & nonCountingFormProducer respectively. */ - static class CountingWrapper extends DelegatingMethodHandle { + static final class CountingWrapper extends DelegatingMethodHandle { private final MethodHandle target; private int count; private Function countingFormProducer; @@ -1299,7 +1299,7 @@ abstract class MethodHandleImpl { } /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */ - private static final class WrappedMember extends DelegatingMethodHandle { + static final class WrappedMember extends DelegatingMethodHandle { private final MethodHandle target; private final MemberName member; private final Class callerClass; 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/NativeMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java index 4c4cd474e1916b9be1ad6e347b9459349da13107..11acea6e508c89612679fa3e5c3fa69820df22eb 100644 --- a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; * or whether a native transition is required) and a fallback method handle, which can be used * when intrinsification of this method handle is not possible. */ -/*non-public*/ class NativeMethodHandle extends MethodHandle { +/*non-public*/ final class NativeMethodHandle extends MethodHandle { final NativeEntryPoint nep; final MethodHandle fallback; 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/VarHandle.java b/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 15dcf63b5c9b5b0df78fe565a85673b55cad2b53..57094d32bb05c09715a49ad969001ca70ceef99e 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.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 @@ -31,15 +31,10 @@ import java.lang.constant.ConstantDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.DirectMethodHandleDesc; import java.lang.constant.DynamicConstantDesc; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.function.BiFunction; -import java.util.function.Function; -import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.DontInline; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; @@ -476,7 +471,41 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE; * @see MethodType * @since 9 */ -public abstract class VarHandle implements Constable { +public abstract sealed class VarHandle implements Constable + permits IndirectVarHandle, MemoryAccessVarHandleBase, + VarHandleByteArrayAsChars.ByteArrayViewVarHandle, + VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle, + VarHandleByteArrayAsFloats.ByteArrayViewVarHandle, + VarHandleByteArrayAsInts.ByteArrayViewVarHandle, + VarHandleByteArrayAsLongs.ByteArrayViewVarHandle, + VarHandleByteArrayAsShorts.ByteArrayViewVarHandle, + VarHandleBooleans.Array, + VarHandleBooleans.FieldInstanceReadOnly, + VarHandleBooleans.FieldStaticReadOnly, + VarHandleBytes.Array, + VarHandleBytes.FieldInstanceReadOnly, + VarHandleBytes.FieldStaticReadOnly, + VarHandleChars.Array, + VarHandleChars.FieldInstanceReadOnly, + VarHandleChars.FieldStaticReadOnly, + VarHandleDoubles.Array, + VarHandleDoubles.FieldInstanceReadOnly, + VarHandleDoubles.FieldStaticReadOnly, + VarHandleFloats.Array, + VarHandleFloats.FieldInstanceReadOnly, + VarHandleFloats.FieldStaticReadOnly, + VarHandleInts.Array, + VarHandleInts.FieldInstanceReadOnly, + VarHandleInts.FieldStaticReadOnly, + VarHandleLongs.Array, + VarHandleLongs.FieldInstanceReadOnly, + VarHandleLongs.FieldStaticReadOnly, + VarHandleReferences.Array, + VarHandleReferences.FieldInstanceReadOnly, + VarHandleReferences.FieldStaticReadOnly, + VarHandleShorts.Array, + VarHandleShorts.FieldInstanceReadOnly, + VarHandleShorts.FieldStaticReadOnly { final VarForm vform; final boolean exact; 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/invoke/X-VarHandle.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index f6196771d1ded25191b20eb856d10dd9af920574..d182056f4eb463cf2de3724890ac80f58b515d59 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -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 @@ -37,7 +37,7 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE; final class VarHandle$Type$s { - static class FieldInstanceReadOnly extends VarHandle { + static sealed class FieldInstanceReadOnly extends VarHandle { final long fieldOffset; final Class receiverType; #if[Object] @@ -381,7 +381,7 @@ final class VarHandle$Type$s { } - static class FieldStaticReadOnly extends VarHandle { + static sealed class FieldStaticReadOnly extends VarHandle { final Object base; final long fieldOffset; #if[Object] diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index 3334b1faef977de232ea3351e3654fd7389928a0..f4c8ee3de80d7fd6bee0f5e195730511e1c2d412 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -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 @@ -71,7 +71,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { #end[floatingPoint] - private static abstract class ByteArrayViewVarHandle extends VarHandle { + static abstract sealed class ByteArrayViewVarHandle extends VarHandle { final boolean be; ByteArrayViewVarHandle(VarForm form, boolean be, boolean exact) { 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/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..2ff3d3375a372a972d4aa92d6109a66fa6681ed3 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 @@ -411,6 +412,9 @@ public class InetAddress implements java.io.Serializable { // Native method to check if IPv4 is available private static native boolean isIPv4Available(); + // Native method to check if IPv6 is available + private static native boolean isIPv6Supported(); + /** * The {@code RuntimePermission("inetAddressResolverProvider")} is * necessary to subclass and instantiate the {@code InetAddressResolverProvider} @@ -1269,7 +1273,8 @@ public class InetAddress implements java.io.Serializable { static { // create the impl - impl = InetAddressImplFactory.create(); + impl = isIPv6Supported() ? + new Inet6AddressImpl() : new Inet4AddressImpl(); // impl must be initialized before calling this method PLATFORM_LOOKUP_POLICY = initializePlatformLookupPolicy(); @@ -1769,16 +1774,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 +1789,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 +1822,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()); @@ -1842,16 +1830,3 @@ public class InetAddress implements java.io.Serializable { s.writeFields(); } } - -/* - * Simple factory to create the impl - */ -class InetAddressImplFactory { - - static InetAddressImpl create() { - return isIPv6Supported() ? - new Inet6AddressImpl() : new Inet4AddressImpl(); - } - - static native boolean isIPv6Supported(); -} 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/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index e2d8bfe755c4577b11d59a887b8e12448c1fa2a4..ffc65492b51139435c9b252ce7dcec7024dc4a35 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -224,6 +224,14 @@ of proxies.

        property is defined, then its value will be used as the domain name.

        +
      • {@systemProperty http.auth.digest.reEnabledAlgorithms} (default: <none>)
        + By default, certain message digest algorithms are disabled for use in HTTP Digest + authentication due to their proven security limitations. This only applies to proxy + authentication and plain-text HTTP server authentication. Disabled algorithms are still + usable for HTTPS server authentication. The default list of disabled algorithms is specified + in the {@code java.security} properties file and currently comprises {@code MD5} and + {@code SHA-1}. If it is still required to use one of these algorithms, then they can be + re-enabled by setting this property to a comma separated list of the algorithm names.

      • {@systemProperty jdk.https.negotiate.cbt} (default: <never>)
        This controls the generation and sending of TLS channel binding tokens (CBT) when Kerberos or the Negotiate authentication scheme using Kerberos are employed over HTTPS with diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index a452b1a28dd435e454104f05c36dc5e4a1dee223..4df2f6206116ede224b8ac310565f4cac6bc1bf1 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.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 @@ -191,7 +191,9 @@ import java.util.Spliterator; * @since 1.4 */ -public abstract class Buffer { +public abstract sealed class Buffer + permits ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, + LongBuffer, ShortBuffer { // Cached unsafe-access object static final Unsafe UNSAFE = Unsafe.getUnsafe(); diff --git a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template index 12788a2b9985fad180f21ddf871f9d450d7ccdda..6040ac7941107f259e483a5845f79670e3970bb9 100644 --- a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,16 @@ import java.util.Objects; import jdk.internal.access.foreign.MemorySegmentProxy; import jdk.internal.misc.Unsafe; +#if[rw] +sealed +#else[rw] +final +#end[rw] class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$} +#if[rw] + permits ByteBufferAs$Type$BufferR$BO$ +#end[rw] { #if[rw] diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index c227cec8e15fedbccb02d083523001b0b2fc0064..38697b394804d3c21f96a7426ac95443e2384795 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-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 @@ -37,6 +37,11 @@ import jdk.internal.ref.Cleaner; import sun.nio.ch.DirectBuffer; +#if[rw] +sealed +#else[rw] +final +#end[rw] class Direct$Type$Buffer$RW$$BO$ #if[rw] extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} @@ -44,6 +49,9 @@ class Direct$Type$Buffer$RW$$BO$ extends Direct$Type$Buffer$BO$ #end[rw] implements DirectBuffer +#if[rw] + permits Direct$Type$BufferR$BO$ +#end[rw] { #if[rw] 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 38e18ac625b9121e9f9e04c41ff9f021e8f71d15..541dbd6c8f8dd77861cecc1ed3782e2fe97fcf52 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 @@ -40,8 +40,16 @@ import jdk.internal.access.foreign.MemorySegmentProxy; * instance of this class rather than of the superclass. #end[rw] */ +#if[rw] +sealed +#else[rw] +final +#end[rw] class Heap$Type$Buffer$RW$ extends {#if[ro]?Heap}$Type$Buffer +#if[rw] + permits Heap$Type$BufferR +#end[rw] { #if[rw] // Cached array base offset diff --git a/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/src/java.base/share/classes/java/nio/MappedByteBuffer.java index 54fb6c869e0503606b21efd23139c8f60c7b090d..8f9ca9f8fe6a7a741273e77fd8f03d261de12b6d 100644 --- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java +++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java @@ -70,8 +70,9 @@ import jdk.internal.misc.Unsafe; * @since 1.4 */ -public abstract class MappedByteBuffer +public abstract sealed class MappedByteBuffer extends ByteBuffer + permits DirectByteBuffer { // This is a little bit backwards: By rights MappedByteBuffer should be a diff --git a/src/java.base/share/classes/java/nio/StringCharBuffer.java b/src/java.base/share/classes/java/nio/StringCharBuffer.java index 40d807a653246ec53464a2d2c57410ab4a1ce37c..a62e802336345a5dd48430a41db21840e675adf2 100644 --- a/src/java.base/share/classes/java/nio/StringCharBuffer.java +++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java @@ -29,7 +29,7 @@ import java.util.Objects; // ## If the sequence is a string, use reflection to share its array -class StringCharBuffer // package-private +final class StringCharBuffer // package-private extends CharBuffer { CharSequence str; diff --git a/src/java.base/share/classes/java/nio/X-Buffer.java.template b/src/java.base/share/classes/java/nio/X-Buffer.java.template index cfedf970f43a55ad8a87df8432adf92c15aa2d43..e559b46f37cb568e607a08da59955ba548c438eb 100644 --- a/src/java.base/share/classes/java/nio/X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/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 @@ -264,9 +264,19 @@ import jdk.internal.util.ArraysSupport; * @since 1.4 */ -public abstract class $Type$Buffer +public abstract sealed class $Type$Buffer extends Buffer implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable} + permits +#if[byte] + Heap$Type$Buffer, MappedByteBuffer +#else[byte] +#if[char] + StringCharBuffer, +#end[char] + Heap$Type$Buffer, Direct$Type$BufferS, Direct$Type$BufferU, + ByteBufferAs$Type$BufferB, ByteBufferAs$Type$BufferL +#end[byte] { // Cached array base offset private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class); 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/Key.java b/src/java.base/share/classes/java/security/Key.java index 4ea5ae0887b08807eec9b9107abb8c1d6885e7ca..b805998a151109195b9fb83435122208f52658e4 100644 --- a/src/java.base/share/classes/java/security/Key.java +++ b/src/java.base/share/classes/java/security/Key.java @@ -63,7 +63,7 @@ package java.security; * * * For more information, see - * RFC 5280: + * RFC 5280: * Internet X.509 Public Key Infrastructure Certificate and CRL Profile. * *

      • A Format @@ -93,8 +93,6 @@ package java.security; * @see KeyFactory * @see KeyRep * @see java.security.spec.KeySpec - * @see Identity - * @see Signer * * @author Benjamin Renaud * @since 1.1 diff --git a/src/java.base/share/classes/java/security/PrivateKey.java b/src/java.base/share/classes/java/security/PrivateKey.java index 3402aa66c8bb8308ffb66d5c9dce7420a7e2a78b..2fb07ab816e9906a9daf15c538f842991ff3b4bb 100644 --- a/src/java.base/share/classes/java/security/PrivateKey.java +++ b/src/java.base/share/classes/java/security/PrivateKey.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 @@ -46,7 +46,7 @@ package java.security; * * @see Key * @see PublicKey - * @see Certificate + * @see java.security.cert.Certificate * @see Signature#initVerify * @see java.security.interfaces.DSAPrivateKey * @see java.security.interfaces.RSAPrivateKey diff --git a/src/java.base/share/classes/java/security/PublicKey.java b/src/java.base/share/classes/java/security/PublicKey.java index dca5bece1bd0bba0537af4852f6c2a3cde6d4709..737273bdbbc44e5a863fa0037a294fec786ae669 100644 --- a/src/java.base/share/classes/java/security/PublicKey.java +++ b/src/java.base/share/classes/java/security/PublicKey.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 @@ -37,7 +37,7 @@ package java.security; * @since 1.1 * @see Key * @see PrivateKey - * @see Certificate + * @see java.security.cert.Certificate * @see Signature#initVerify * @see java.security.interfaces.DSAPublicKey * @see java.security.interfaces.RSAPublicKey diff --git a/src/java.base/share/classes/java/security/SecureRandom.java b/src/java.base/share/classes/java/security/SecureRandom.java index 1cf18d74a0fcbdb64fa94e9de3aa733de3b9099c..02422b77bc3427c17983657275a57dc34e9355fb 100644 --- a/src/java.base/share/classes/java/security/SecureRandom.java +++ b/src/java.base/share/classes/java/security/SecureRandom.java @@ -50,7 +50,7 @@ import sun.security.util.Debug; * Therefore any seed material passed to a {@code SecureRandom} object must be * unpredictable, and all {@code SecureRandom} output sequences must be * cryptographically strong, as described in - * + * * RFC 4086: Randomness Requirements for Security. * *

        Many {@code SecureRandom} implementations are in the form of a diff --git a/src/java.base/share/classes/java/security/cert/CRLReason.java b/src/java.base/share/classes/java/security/cert/CRLReason.java index 79d4729d0b8a48fd176fb744b8c730aed32bed50..2bc83f3356b29e4a9d4e8e3c14e87becd31f5a81 100644 --- a/src/java.base/share/classes/java/security/cert/CRLReason.java +++ b/src/java.base/share/classes/java/security/cert/CRLReason.java @@ -27,7 +27,7 @@ package java.security.cert; /** * The CRLReason enumeration specifies the reason that a certificate - * is revoked, as defined in + * is revoked, as defined in * RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL * Profile. * diff --git a/src/java.base/share/classes/java/security/cert/TrustAnchor.java b/src/java.base/share/classes/java/security/cert/TrustAnchor.java index ab60b5cbd9ae6828e4805ff6e4a61a7f3d300927..2626bcf3c2ddd073dd889bc6314c1658ff55bd31 100644 --- a/src/java.base/share/classes/java/security/cert/TrustAnchor.java +++ b/src/java.base/share/classes/java/security/cert/TrustAnchor.java @@ -84,7 +84,7 @@ public class TrustAnchor { * The name constraints are specified as a byte array. This byte array * should contain the DER encoded form of the name constraints, as they * would appear in the NameConstraints structure defined in - * RFC 5280 + * RFC 5280 * and X.509. The ASN.1 definition of this structure appears below. * *

        {@code
        diff --git a/src/java.base/share/classes/java/security/cert/X509CRL.java b/src/java.base/share/classes/java/security/cert/X509CRL.java
        index a9f3d2939aaf86cb7f86048168e738caa032ed69..48982d70adac199b27bb47631f3e8c85fcd9c618 100644
        --- a/src/java.base/share/classes/java/security/cert/X509CRL.java
        +++ b/src/java.base/share/classes/java/security/cert/X509CRL.java
        @@ -66,7 +66,7 @@ import sun.security.util.SignatureUtil;
          * 
        *

        * More information can be found in - * RFC 5280: Internet X.509 + * RFC 5280: Internet X.509 * Public Key Infrastructure Certificate and CRL Profile. *

        * The ASN.1 definition of {@code tbsCertList} is: diff --git a/src/java.base/share/classes/java/security/cert/X509CRLSelector.java b/src/java.base/share/classes/java/security/cert/X509CRLSelector.java index 444100cbdccd1c105ac8db164c1ec8565d452e7f..45bc470c8c166aa7cbd5647e6428700d1e995e6a 100644 --- a/src/java.base/share/classes/java/security/cert/X509CRLSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CRLSelector.java @@ -53,7 +53,7 @@ import sun.security.x509.X500Name; * {@link CertStore#getCRLs CertStore.getCRLs} or some similar * method. *

        - * Please refer to RFC 5280: + * Please refer to RFC 5280: * Internet X.509 Public Key Infrastructure Certificate and CRL Profile * for definitions of the X.509 CRL fields and extensions mentioned below. *

        diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java index 5a25ba5927f1a9f1815b7c0cd9375e56810cf34c..291ff5bee8304a6faba718b1b86e0f7de5a456a2 100644 --- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java @@ -62,7 +62,7 @@ import sun.security.x509.*; * number. Other unique combinations include the issuer, subject, * subjectKeyIdentifier and/or the subjectPublicKey criteria. *

        - * Please refer to RFC 5280: + * Please refer to RFC 5280: * Internet X.509 Public Key Infrastructure Certificate and CRL Profile for * definitions of the X.509 certificate extensions mentioned below. *

        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 127f60b41806cdb1a908328fd4aef35be42d815b..a05f957ac9736dbc815dcc6131a758fd1aa1ba89 100644 --- a/src/java.base/share/classes/java/security/cert/X509Certificate.java +++ b/src/java.base/share/classes/java/security/cert/X509Certificate.java @@ -65,7 +65,7 @@ import sun.security.util.SignatureUtil; * CA such as a "root" CA. *

        * More information can be found in - * RFC 5280: Internet X.509 + * RFC 5280: Internet X.509 * Public Key Infrastructure Certificate and CRL Profile. *

        * The ASN.1 definition of {@code tbsCertificate} is: diff --git a/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java b/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java index ddc32291dfe4bd2e6118a4532a6181ee5ecb63fd..b6603279e047f1f8cc0608d67d5aaf8256bbb0ef 100644 --- a/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java +++ b/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,11 +28,11 @@ package java.security.spec; import java.util.Objects; /** - * This class specifies a parameter spec for RSASSA-PSS signature scheme, + * This class specifies a parameter spec for the RSASSA-PSS signature scheme, * as defined in the * PKCS#1 v2.2 standard. * - *

        Its ASN.1 definition in PKCS#1 standard is described below: + *

        Its ASN.1 definition in the PKCS #1 standard is described below: *

          * RSASSA-PSS-params ::= SEQUENCE {
          *   hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
        @@ -64,12 +64,6 @@ import java.util.Objects;
          *   ...  -- Allows for future expansion --
          * }
          * 
        - *

        Note: the PSSParameterSpec.DEFAULT uses the following: - * message digest -- "SHA-1" - * mask generation function (mgf) -- "MGF1" - * parameters for mgf -- MGF1ParameterSpec.SHA1 - * SaltLength -- 20 - * TrailerField -- 1 * * @see MGF1ParameterSpec * @see AlgorithmParameterSpec @@ -94,17 +88,26 @@ public class PSSParameterSpec implements AlgorithmParameterSpec { private final int trailerField; /** - * The {@code TrailerFieldBC} constant as defined in PKCS#1 + * The {@code TrailerFieldBC} constant as defined in the PKCS #1 standard. * * @since 11 */ public static final int TRAILER_FIELD_BC = 1; /** - * The PSS parameter set with all default values + * The PSS parameter set with all default values. + * @deprecated This field uses the default values defined in the PKCS #1 + * standard. Some of these defaults are no longer recommended due + * to advances in cryptanalysis -- see the + * PKCS#1 v2.2 + * standard for more details. Thus, it is recommended to create + * a new {@code PSSParameterSpec} with the desired parameter values + * using the + * {@link #PSSParameterSpec(String, String, AlgorithmParameterSpec, int, int)} constructor. * * @since 1.5 */ + @Deprecated(since="19") public static final PSSParameterSpec DEFAULT = new PSSParameterSpec ("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, 20, TRAILER_FIELD_BC); @@ -126,7 +129,7 @@ public class PSSParameterSpec implements AlgorithmParameterSpec { * @param mgfSpec the parameters for the mask generation function. * If null is specified, null will be returned by * getMGFParameters(). - * @param saltLen the length of salt + * @param saltLen the length of salt in bytes * @param trailerField the value of the trailer field * @throws NullPointerException if {@code mdName}, or {@code mgfName} * is null @@ -157,13 +160,21 @@ public class PSSParameterSpec implements AlgorithmParameterSpec { /** * Creates a new {@code PSSParameterSpec} * using the specified salt length and other default values as - * defined in PKCS#1. + * defined in the PKCS #1 standard. * - * @param saltLen the length of salt in bytes to be used in PKCS#1 - * PSS encoding + * @param saltLen the length of salt in bytes * @throws IllegalArgumentException if {@code saltLen} is * less than 0 + * @deprecated This constructor uses the default values defined in + * the PKCS #1 standard except for the salt length. Some of these + * defaults are no longer recommended due to advances in + * cryptanalysis -- see the + * PKCS#1 v2.2 + * standard for more details. Thus, it is recommended to explicitly + * specify all desired parameter values with the + * {@link #PSSParameterSpec(String, String, AlgorithmParameterSpec, int, int)} constructor. */ + @Deprecated(since="19") public PSSParameterSpec(int saltLen) { this("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, saltLen, TRAILER_FIELD_BC); } 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/LocalDate.java b/src/java.base/share/classes/java/time/LocalDate.java index 4564355e8bbaeae268f1e5287ba21a1babe61c4c..e383f22649390c7e169f1cce948709bdca1be8a6 100644 --- a/src/java.base/share/classes/java/time/LocalDate.java +++ b/src/java.base/share/classes/java/time/LocalDate.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 @@ -363,13 +363,16 @@ public final class LocalDate // convert march-based values back to january-based int marchMonth0 = (marchDoy0 * 5 + 2) / 153; - int month = (marchMonth0 + 2) % 12 + 1; + int month = marchMonth0 + 3; + if (month > 12) { + month -= 12; + } int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1; - yearEst += marchMonth0 / 10; + if (marchDoy0 >= 306) { + yearEst++; + } - // check year now we are certain it is correct - int year = YEAR.checkValidIntValue(yearEst); - return new LocalDate(year, month, dom); + return new LocalDate((int)yearEst, month, dom); } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/ZoneId.java b/src/java.base/share/classes/java/time/ZoneId.java index 829ed5f2fdf25724caebfcaacdc8bcc8894a3974..14196c160fba540164d78f2282f3b7c2a0f8a272 100644 --- a/src/java.base/share/classes/java/time/ZoneId.java +++ b/src/java.base/share/classes/java/time/ZoneId.java @@ -584,6 +584,11 @@ public abstract sealed class ZoneId implements Serializable permits ZoneOffset, return this; } + /** + * Get the effective offset for an instant at the given epochSecond. + */ + /* package-private */ abstract ZoneOffset getOffset(long epochSecond); + //----------------------------------------------------------------------- /** * Checks if this time-zone ID is equal to another time-zone ID. diff --git a/src/java.base/share/classes/java/time/ZoneOffset.java b/src/java.base/share/classes/java/time/ZoneOffset.java index f061040b9e2ecf9b41e90a27947f2c9f67cf3e4d..9dd647894095ed0fc9710e03df3ebecec75aabfb 100644 --- a/src/java.base/share/classes/java/time/ZoneOffset.java +++ b/src/java.base/share/classes/java/time/ZoneOffset.java @@ -86,6 +86,8 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import jdk.internal.vm.annotation.Stable; + /** * A time-zone offset from Greenwich/UTC, such as {@code +02:00}. *

        @@ -168,6 +170,11 @@ public final class ZoneOffset * The string form of the time-zone offset. */ private final transient String id; + /** + * The zone rules for an offset will always return this offset. Cache it for efficiency. + */ + @Stable + private transient ZoneRules rules; //----------------------------------------------------------------------- /** @@ -504,7 +511,21 @@ public final class ZoneOffset */ @Override public ZoneRules getRules() { - return ZoneRules.of(this); + ZoneRules rules = this.rules; + if (rules == null) { + rules = this.rules = ZoneRules.of(this); + } + return rules; + } + + @Override + public ZoneId normalized() { + return this; + } + + @Override + /* package-private */ ZoneOffset getOffset(long epochSecond) { + return this; } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/ZoneRegion.java b/src/java.base/share/classes/java/time/ZoneRegion.java index aec8a2b108b8e1d38adeb3642026d6a63f79a59d..9a7e66f0943cd2ff61a6d477b6e87d5847cf9469 100644 --- a/src/java.base/share/classes/java/time/ZoneRegion.java +++ b/src/java.base/share/classes/java/time/ZoneRegion.java @@ -178,6 +178,11 @@ final class ZoneRegion extends ZoneId implements Serializable { return (rules != null ? rules : ZoneRulesProvider.getRules(id, false)); } + @Override + /* package-private */ ZoneOffset getOffset(long epochSecond) { + return getRules().getOffset(Instant.ofEpochSecond(epochSecond)); + } + //----------------------------------------------------------------------- /** * Writes the object using a diff --git a/src/java.base/share/classes/java/time/ZonedDateTime.java b/src/java.base/share/classes/java/time/ZonedDateTime.java index acd68706b1ca155ce34757243828201e527b0c98..555392cf513ce90e6acaefcfed0276d2ed01a67c 100644 --- a/src/java.base/share/classes/java/time/ZonedDateTime.java +++ b/src/java.base/share/classes/java/time/ZonedDateTime.java @@ -452,9 +452,9 @@ public final class ZonedDateTime * @throws DateTimeException if the result exceeds the supported range */ private static ZonedDateTime create(long epochSecond, int nanoOfSecond, ZoneId zone) { - ZoneRules rules = zone.getRules(); - Instant instant = Instant.ofEpochSecond(epochSecond, nanoOfSecond); // TODO: rules should be queryable by epochSeconds - ZoneOffset offset = rules.getOffset(instant); + // nanoOfSecond is in a range that'll not affect epochSecond, validated + // by LocalDateTime.ofEpochSecond + ZoneOffset offset = zone.getOffset(epochSecond); LocalDateTime ldt = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, offset); return new ZonedDateTime(ldt, offset, zone); } diff --git a/src/java.base/share/classes/java/time/zone/ZoneRules.java b/src/java.base/share/classes/java/time/zone/ZoneRules.java index 1e1e95abba8df7fa44b347b71042d2dce600a277..480ff2bb27cc4363ad0ee1d93000a9c255e220ad 100644 --- a/src/java.base/share/classes/java/time/zone/ZoneRules.java +++ b/src/java.base/share/classes/java/time/zone/ZoneRules.java @@ -146,8 +146,7 @@ public final class ZoneRules implements Serializable { /** * The map of recent transitions. */ - private final transient ConcurrentMap lastRulesCache = - new ConcurrentHashMap(); + private final transient ConcurrentMap lastRulesCache; /** * The zero-length long array. */ @@ -259,12 +258,18 @@ public final class ZoneRules implements Serializable { } // last rules - Object[] temp = lastRules.toArray(); - ZoneOffsetTransitionRule[] rulesArray = Arrays.copyOf(temp, temp.length, ZoneOffsetTransitionRule[].class); - if (rulesArray.length > 16) { - throw new IllegalArgumentException("Too many transition rules"); + if (lastRules.size() > 0) { + Object[] temp = lastRules.toArray(); + ZoneOffsetTransitionRule[] rulesArray = Arrays.copyOf(temp, temp.length, ZoneOffsetTransitionRule[].class); + if (rulesArray.length > 16) { + throw new IllegalArgumentException("Too many transition rules"); + } + this.lastRules = rulesArray; + this.lastRulesCache = new ConcurrentHashMap<>(); + } else { + this.lastRules = EMPTY_LASTRULES; + this.lastRulesCache = null; } - this.lastRules = rulesArray; } /** @@ -288,6 +293,7 @@ public final class ZoneRules implements Serializable { this.savingsInstantTransitions = savingsInstantTransitions; this.wallOffsets = wallOffsets; this.lastRules = lastRules; + this.lastRulesCache = (lastRules.length > 0) ? new ConcurrentHashMap<>() : null; if (savingsInstantTransitions.length == 0) { this.savingsLocalTransitions = EMPTY_LDT_ARRAY; @@ -324,6 +330,7 @@ public final class ZoneRules implements Serializable { this.savingsLocalTransitions = EMPTY_LDT_ARRAY; this.wallOffsets = standardOffsets; this.lastRules = EMPTY_LASTRULES; + this.lastRulesCache = null; } /** @@ -967,11 +974,11 @@ public final class ZoneRules implements Serializable { doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400); } yearEst += adjust; // reset any negative year - int marchDoy0 = (int) doyEst; - // convert march-based values back to january-based - int marchMonth0 = (marchDoy0 * 5 + 2) / 153; - yearEst += marchMonth0 / 10; + // convert march-based values back to january-based, adjust year + if (doyEst >= 306) { + yearEst++; + } // Cap to the max value return (int)Math.min(yearEst, Year.MAX_VALUE); diff --git a/src/java.base/share/classes/java/util/DuplicateFormatFlagsException.java b/src/java.base/share/classes/java/util/DuplicateFormatFlagsException.java index 356ea209c92f425d219fec3bc225e65b2efbfef3..ebeb3d5c44c0a7b1e773746322b76afaf44143b2 100644 --- a/src/java.base/share/classes/java/util/DuplicateFormatFlagsException.java +++ b/src/java.base/share/classes/java/util/DuplicateFormatFlagsException.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 @@ -35,7 +35,7 @@ package java.util; * * @since 1.5 */ -public class DuplicateFormatFlagsException extends IllegalFormatException { +public non-sealed class DuplicateFormatFlagsException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 18890531L; 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/FormatFlagsConversionMismatchException.java b/src/java.base/share/classes/java/util/FormatFlagsConversionMismatchException.java index 6f2464d4fb6d12a5c611499c43ad48e292d5dd2b..cca7b3eb5532294d1d6bc19131722c676a51699e 100644 --- a/src/java.base/share/classes/java/util/FormatFlagsConversionMismatchException.java +++ b/src/java.base/share/classes/java/util/FormatFlagsConversionMismatchException.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 @@ -34,7 +34,7 @@ package java.util; * * @since 1.5 */ -public class FormatFlagsConversionMismatchException +public non-sealed class FormatFlagsConversionMismatchException extends IllegalFormatException { @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/IllegalFormatArgumentIndexException.java b/src/java.base/share/classes/java/util/IllegalFormatArgumentIndexException.java index 02d5449098dd9a96360de247e057806ffbf7c511..64b24411592ae62343396572a75984f0a8b38444 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatArgumentIndexException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatArgumentIndexException.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 @@ -33,7 +33,7 @@ package java.util; * * @since 16 */ -class IllegalFormatArgumentIndexException extends IllegalFormatException { +final class IllegalFormatArgumentIndexException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 4191767811181838112L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatCodePointException.java b/src/java.base/share/classes/java/util/IllegalFormatCodePointException.java index 14ec9137f1ed46510733d81e04e7344afd252a47..2f1803d220ecfc4e6086326505460e83a06b9e5d 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatCodePointException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatCodePointException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ package java.util; * * @since 1.5 */ -public class IllegalFormatCodePointException extends IllegalFormatException { +public non-sealed class IllegalFormatCodePointException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 19080630L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatConversionException.java b/src/java.base/share/classes/java/util/IllegalFormatConversionException.java index 2dacf2094b4531a5068ddcc468566214a9e6350e..67237f63cdf20545a2e80cb15b94814420fd90d2 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatConversionException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatConversionException.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 @@ -35,7 +35,7 @@ package java.util; * * @since 1.5 */ -public class IllegalFormatConversionException extends IllegalFormatException { +public non-sealed class IllegalFormatConversionException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 17000126L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatException.java b/src/java.base/share/classes/java/util/IllegalFormatException.java index 97b85cc107e211a35b9dc150a63ff6e841f49bcc..f5be4ad268b301a410c9d492ce5b33512a98edb1 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatException.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,19 @@ package java.util; * * @since 1.5 */ -public class IllegalFormatException extends IllegalArgumentException { +public sealed class IllegalFormatException extends IllegalArgumentException + permits DuplicateFormatFlagsException, + FormatFlagsConversionMismatchException, + IllegalFormatArgumentIndexException, + IllegalFormatCodePointException, + IllegalFormatConversionException, + IllegalFormatFlagsException, + IllegalFormatPrecisionException, + IllegalFormatWidthException, + MissingFormatArgumentException, + MissingFormatWidthException, + UnknownFormatConversionException, + UnknownFormatFlagsException { @java.io.Serial private static final long serialVersionUID = 18830826L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatFlagsException.java b/src/java.base/share/classes/java/util/IllegalFormatFlagsException.java index 38e4e2d577e4b125bccac470f058cb800b370eed..408fa1efa5c24876f75b1344e2c0769b4d43c7cf 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatFlagsException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatFlagsException.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 @@ -34,7 +34,7 @@ package java.util; * * @since 1.5 */ -public class IllegalFormatFlagsException extends IllegalFormatException { +public non-sealed class IllegalFormatFlagsException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 790824L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatPrecisionException.java b/src/java.base/share/classes/java/util/IllegalFormatPrecisionException.java index bdf3de6f52831687ff0bcdc8ed6df2299b6d38f6..4527953790c1d2beaec45a93139dddfc2039fffb 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatPrecisionException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatPrecisionException.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 @@ -34,7 +34,7 @@ package java.util; * * @since 1.5 */ -public class IllegalFormatPrecisionException extends IllegalFormatException { +public non-sealed class IllegalFormatPrecisionException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 18711008L; diff --git a/src/java.base/share/classes/java/util/IllegalFormatWidthException.java b/src/java.base/share/classes/java/util/IllegalFormatWidthException.java index e00ec01eee07626cd758423fde4a2e4b71ad46fc..df8d59b9e812bd3fa8ca4e2638cd313d56e58d19 100644 --- a/src/java.base/share/classes/java/util/IllegalFormatWidthException.java +++ b/src/java.base/share/classes/java/util/IllegalFormatWidthException.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 */ -public class IllegalFormatWidthException extends IllegalFormatException { +public non-sealed class IllegalFormatWidthException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 16660902L; 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/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 2da179a5dd7b74b6144b3d2f027e9f2d14d65cda..0ab6fbad86f364d7822a338aa9c08cbfd1a7d38d 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -75,8 +75,8 @@ import sun.util.locale.provider.TimeZoneNameUtility; * region, or culture. * *

        The {@code Locale} class implements IETF BCP 47 which is composed of - * RFC 4647 "Matching of Language - * Tags" and RFC 5646 "Tags + * RFC 4647 "Matching of Language + * Tags" and RFC 5646 "Tags * for Identifying Languages" with support for the LDML (UTS#35, "Unicode * Locale Data Markup Language") BCP 47-compatible extensions for locale data * exchange. @@ -230,9 +230,9 @@ import sun.util.locale.provider.TimeZoneNameUtility; * implementations in a Java Runtime Environment might not support any * particular Unicode locale attributes or key/type pairs. * - *

        Creating a Locale

        + *

        Obtaining a Locale

        * - *

        There are several different ways to create a {@code Locale} + *

        There are several ways to obtain a {@code Locale} * object. * *

        Builder

        @@ -240,36 +240,20 @@ import sun.util.locale.provider.TimeZoneNameUtility; *

        Using {@link Builder} you can construct a {@code Locale} object * that conforms to BCP 47 syntax. * - *

        Constructors

        - * - *

        The {@code Locale} class provides three constructors: - *

        - *
        - *     {@link #Locale(String language)}
        - *     {@link #Locale(String language, String country)}
        - *     {@link #Locale(String language, String country, String variant)}
        - * 
        - *
        - * These constructors allow you to create a {@code Locale} object - * with language, country and variant, but you cannot specify - * script or extensions. - * *

        Factory Methods

        * - *

        The method {@link #forLanguageTag} creates a {@code Locale} - * object for a well-formed BCP 47 language tag. + *

        The method {@link #forLanguageTag} obtains a {@code Locale} + * object for a well-formed BCP 47 language tag. The method + * {@link #of(String, String, String)} and its overloads obtain a + * {@code Locale} object from given {@code language}, {@code country}, + * and/or {@code variant} defined above. * *

        Locale Constants

        * *

        The {@code Locale} class provides a number of convenient constants - * that you can use to create {@code Locale} objects for commonly used - * locales. For example, the following creates a {@code Locale} object - * for the United States: - *

        - *
        - *     Locale.US
        - * 
        - *
        + * that you can use to obtain {@code Locale} objects for commonly used + * locales. For example, {@code Locale.US} is the {@code Locale} object + * for the United States. * *

        Locale Matching

        * @@ -280,7 +264,7 @@ import sun.util.locale.provider.TimeZoneNameUtility; * locale matching documentation. * *

        In order to do matching a user's preferred locales to a set of language - * tags, RFC 4647 Matching of + * tags, RFC 4647 Matching of * Language Tags defines two mechanisms: filtering and lookup. * Filtering is used to get all matching locales, whereas * lookup is to choose the best matching locale. @@ -344,7 +328,7 @@ import sun.util.locale.provider.TimeZoneNameUtility; * *

        Use of Locale

        * - *

        Once you've created a {@code Locale} you can query it for information + *

        Once you've obtained a {@code Locale} you can query it for information * about itself. Use {@code getCountry} to get the country (or region) * code and {@code getLanguage} to get the language code. * You can use {@code getDisplayCountry} to get the @@ -387,7 +371,7 @@ import sun.util.locale.provider.TimeZoneNameUtility; * *

        Compatibility

        * - *

        In order to maintain compatibility with existing usage, Locale's + *

        In order to maintain compatibility, Locale's * constructors retain their behavior prior to the Java Runtime * Environment version 1.7. The same is largely true for the * {@code toString} method. Thus Locale objects can continue to @@ -741,6 +725,9 @@ public final class Locale implements Cloneable, Serializable { * see Special Cases for more information. *

      * + * @deprecated Locale constructors have been deprecated. See + * Obtaining a Locale for other options. + * * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag * up to 8 characters in length. See the {@code Locale} class description about * valid language values. @@ -750,6 +737,7 @@ public final class Locale implements Cloneable, Serializable { * See the {@code Locale} class description for the details. * @throws NullPointerException thrown if any argument is null. */ + @Deprecated(since="19") public Locale(String language, String country, String variant) { if (language == null || country == null || variant == null) { throw new NullPointerException(); @@ -771,6 +759,9 @@ public final class Locale implements Cloneable, Serializable { * any syntactic checks on the input. *
    * + * @deprecated Locale constructors have been deprecated. See + * Obtaining a Locale for other options. + * * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag * up to 8 characters in length. See the {@code Locale} class description about * valid language values. @@ -778,6 +769,7 @@ public final class Locale implements Cloneable, Serializable { * See the {@code Locale} class description about valid country values. * @throws NullPointerException thrown if either argument is null. */ + @Deprecated(since="19") public Locale(String language, String country) { this(language, country, ""); } @@ -794,16 +786,96 @@ public final class Locale implements Cloneable, Serializable { * any syntactic checks on the input. * * + * @deprecated Locale constructors have been deprecated. See + * Obtaining a Locale for other options. + * * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag * up to 8 characters in length. See the {@code Locale} class description about * valid language values. * @throws NullPointerException thrown if argument is null. * @since 1.4 */ + @Deprecated(since="19") public Locale(String language) { this(language, "", ""); } + /** + * Obtains a locale from language, country and variant. + * This method normalizes the language value to lowercase and + * the country value to uppercase. + * @implNote + *
      + *
    • This method does not make any syntactic checks on the input. + * Use {@link Locale.Builder} for full syntactic checks with BCP47. + *
    • The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially, + * see Special Cases for more information. + *
    • Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to + * their current forms. See Legacy language + * codes for more information. + *
    + * + * @param language A language code. See the {@code Locale} class description of + * language values. + * @param country A country code. See the {@code Locale} class description of + * country values. + * @param variant Any arbitrary value used to indicate a variation of a {@code Locale}. + * See the {@code Locale} class description of variant values. + * @throws NullPointerException thrown if any argument is null. + * @return A {@code Locale} object + * @since 19 + */ + public static Locale of(String language, String country, String variant) { + return getInstance(language, "", country, variant, null); + } + + /** + * Obtains a locale from language and country. + * This method normalizes the language value to lowercase and + * the country value to uppercase. + * @implNote + *
      + *
    • This method does not make any syntactic checks on the input. + * Use {@link Locale.Builder} for full syntactic checks with BCP47. + *
    • Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to + * their current forms. See Legacy language + * codes for more information. + *
    + * + * @param language A language code. See the {@code Locale} class description of + * language values. + * @param country A country code. See the {@code Locale} class description of + * country values. + * @throws NullPointerException thrown if either argument is null. + * @return A {@code Locale} object + * @since 19 + */ + public static Locale of(String language, String country) { + return getInstance(language, "", country, "", null); + } + + /** + * Obtains a locale from a language code. + * This method normalizes the language value to lowercase. + * @implNote + *
      + *
    • This method does not make any syntactic checks on the input. + * Use {@link Locale.Builder} for full syntactic checks with BCP47. + *
    • Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to + * their current forms. See Legacy language + * codes for more information. + *
    + * + * @param language A language code. See the {@code Locale} class description of + * language values. + * @throws NullPointerException thrown if argument is null. + * @return A {@code Locale} object + * @since 19 + */ + public static Locale of(String language) { + return getInstance(language, "", "", "", null); + } + /** * Returns a {@code Locale} constructed from the given * {@code language}, {@code country} and @@ -1138,14 +1210,14 @@ public final class Locale implements Cloneable, Serializable { /** * Returns a list of all 2-letter country codes defined in ISO 3166. - * Can be used to create Locales. + * Can be used to obtain Locales. * This method is equivalent to {@link #getISOCountries(Locale.IsoCountryCode type)} * with {@code type} {@link IsoCountryCode#PART1_ALPHA2}. *

    * Note: The {@code Locale} class also supports other codes for * country (region), such as 3-letter numeric UN M.49 area codes. * Therefore, the list returned by this method does not contain ALL valid - * codes that can be used to create Locales. + * codes that can be used to obtain Locales. *

    * Note that this method does not return obsolete 2-letter country codes. * ISO3166-3 codes which designate country codes for those obsolete codes, @@ -1178,7 +1250,7 @@ public final class Locale implements Cloneable, Serializable { /** * Returns a list of all 2-letter language codes defined in ISO 639. - * Can be used to create Locales. + * Can be used to obtain Locales. *

    * Note: *

      @@ -1187,7 +1259,7 @@ public final class Locale implements Cloneable, Serializable { * languages whose codes have changed. *
    • The {@code Locale} class also supports language codes up to * 8 characters in length. Therefore, the list returned by this method does - * not contain ALL valid codes that can be used to create Locales. + * not contain ALL valid codes that can be used to obtain Locales. *
    * * @return An array of ISO 639 two-letter language codes. @@ -1520,12 +1592,12 @@ public final class Locale implements Cloneable, Serializable { * "NY", representing Norwegian Nynorsk (Norway), is converted * to a language tag "nn-NO". * - *

    Note: Although the language tag created by this + *

    Note: Although the language tag obtained by this * method is well-formed (satisfies the syntax requirements * defined by the IETF BCP 47 specification), it is not * necessarily a valid BCP 47 language tag. For example, *

    -     *   new Locale("xx", "YY").toLanguageTag();
    + * Locale.forLanguageTag("xx-YY").toLanguageTag(); * * will return "xx-YY", but the language subtag "xx" and the * region subtag "YY" are invalid because they are not registered @@ -2510,7 +2582,7 @@ public final class Locale implements Cloneable, Serializable { * from values configured by the setters. Unlike the {@code Locale} * constructors, the {@code Builder} checks if a value configured by a * setter satisfies the syntax requirements defined by the {@code Locale} - * class. A {@code Locale} object created by a {@code Builder} is + * class. A {@code Locale} object obtained from a {@code Builder} is * well-formed and can be transformed to a well-formed IETF BCP 47 language tag * without losing information. * @@ -2521,11 +2593,11 @@ public final class Locale implements Cloneable, Serializable { * {@code IllformedLocaleException} for a variant that does not satisfy * this restriction. If it is necessary to support such a variant, use a * Locale constructor. However, keep in mind that a {@code Locale} - * object created this way might lose the variant information when + * object obtained this way might lose the variant information when * transformed to a BCP 47 language tag. * - *

    The following example shows how to create a {@code Locale} object - * with the {@code Builder}. + *

    The following example shows how to obtain a {@code Locale} object + * using a {@code Builder}. *

    *
          *     Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
    @@ -2658,7 +2730,7 @@ public final class Locale implements Cloneable, Serializable {
              * 

    The typical region value is a two-letter ISO 3166 code or a * three-digit UN M.49 area code. * - *

    The country value in the {@code Locale} created by the + *

    The country value in the {@code Locale} obtained from a * {@code Builder} is always normalized to upper case. * * @param region the region @@ -2831,7 +2903,7 @@ public final class Locale implements Cloneable, Serializable { } /** - * Returns an instance of {@code Locale} created from the fields set + * Returns an instance of {@code Locale} obtained from the fields set * on this builder. * *

    This applies the conversions listed in {@link Locale#forLanguageTag} @@ -2853,7 +2925,7 @@ public final class Locale implements Cloneable, Serializable { /** * This enum provides constants to select a filtering mode for locale - * matching. Refer to RFC 4647 + * matching. Refer to RFC 4647 * Matching of Language Tags for details. * *

    As an example, think of two Language Priority Lists each of which @@ -2989,7 +3061,7 @@ public final class Locale implements Cloneable, Serializable { /** * This class expresses a Language Range defined in - * RFC 4647 Matching of + * RFC 4647 Matching of * Language Tags. A language range is an identifier which is used to * select language tag(s) meeting specific requirements by using the * mechanisms described in Locale @@ -2998,7 +3070,7 @@ public final class Locale implements Cloneable, Serializable { * *

    There are two types of language ranges: basic and extended. In RFC * 4647, the syntax of language ranges is expressed in - * ABNF as follows: + * ABNF as follows: *

    *
          *     basic-language-range    = (1*8ALPHA *("-" 1*8alphanum)) / "*"
    @@ -3164,7 +3236,7 @@ public final class Locale implements Cloneable, Serializable {
              *
              * In a weighted list, each language range is given a weight value.
              * The weight value is identical to the "quality value" in
    -         * RFC 2616, and it
    +         * RFC 2616, and it
              * expresses how much the user prefers  the language. A weight value is
              * specified after a corresponding language range followed by
              * {@code ";q="}, and the default weight value is {@code MAX_WEIGHT}
    @@ -3202,7 +3274,7 @@ public final class Locale implements Cloneable, Serializable {
              *
              * @param ranges a list of comma-separated language ranges or a list of
              *     language ranges in the form of the "Accept-Language" header
    -         *     defined in RFC
    +         *     defined in RFC
              *     2616
              * @return a Language Priority List consisting of language ranges
              *     included in the given {@code ranges} and their equivalent
    @@ -3223,7 +3295,7 @@ public final class Locale implements Cloneable, Serializable {
              *
              * @param ranges a list of comma-separated language ranges or a list
              *     of language ranges in the form of the "Accept-Language" header
    -         *     defined in RFC
    +         *     defined in RFC
              *     2616
              * @param map a map containing information to customize language ranges
              * @return a Language Priority List with customization. The list is
    diff --git a/src/java.base/share/classes/java/util/MissingFormatArgumentException.java b/src/java.base/share/classes/java/util/MissingFormatArgumentException.java
    index dcb0847833b25e11173cd16823053b4a4ce13119..6363566216bdb2414d827c0ced76ee79eea33a65 100644
    --- a/src/java.base/share/classes/java/util/MissingFormatArgumentException.java
    +++ b/src/java.base/share/classes/java/util/MissingFormatArgumentException.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -36,7 +36,7 @@ package java.util;
      *
      * @since 1.5
      */
    -public class MissingFormatArgumentException extends IllegalFormatException {
    +public non-sealed class MissingFormatArgumentException extends IllegalFormatException {
     
         @java.io.Serial
         private static final long serialVersionUID = 19190115L;
    diff --git a/src/java.base/share/classes/java/util/MissingFormatWidthException.java b/src/java.base/share/classes/java/util/MissingFormatWidthException.java
    index 0ce9c3af83ce6789159a4be3d068b2680bf3e3b7..b553a3876ac13a831704e0a4ec3e2c34192bba28 100644
    --- a/src/java.base/share/classes/java/util/MissingFormatWidthException.java
    +++ b/src/java.base/share/classes/java/util/MissingFormatWidthException.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
    @@ -34,7 +34,7 @@ package java.util;
      *
      * @since 1.5
      */
    -public class MissingFormatWidthException extends IllegalFormatException {
    +public non-sealed class MissingFormatWidthException extends IllegalFormatException {
     
         @java.io.Serial
         private static final long serialVersionUID = 15560123L;
    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/UUID.java b/src/java.base/share/classes/java/util/UUID.java index 0378df95a79863f16eaf068a6854cec2cde55a6d..e88d77ae63e7c3b311204cab0cfd2bcb38ab0140 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.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 @@ -264,7 +264,7 @@ public final class UUID implements java.io.Serializable, Comparable { throw new IllegalArgumentException("UUID string too large"); } - int dash1 = name.indexOf('-', 0); + int dash1 = name.indexOf('-'); int dash2 = name.indexOf('-', dash1 + 1); int dash3 = name.indexOf('-', dash2 + 1); int dash4 = name.indexOf('-', dash3 + 1); diff --git a/src/java.base/share/classes/java/util/UnknownFormatConversionException.java b/src/java.base/share/classes/java/util/UnknownFormatConversionException.java index 07519ade1701b5c5a134f51342c937a34e5c913d..13d428e0b60f3337b9e055ec5adbe0e8a87846f7 100644 --- a/src/java.base/share/classes/java/util/UnknownFormatConversionException.java +++ b/src/java.base/share/classes/java/util/UnknownFormatConversionException.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 @@ -34,7 +34,7 @@ package java.util; * * @since 1.5 */ -public class UnknownFormatConversionException extends IllegalFormatException { +public non-sealed class UnknownFormatConversionException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 19060418L; diff --git a/src/java.base/share/classes/java/util/UnknownFormatFlagsException.java b/src/java.base/share/classes/java/util/UnknownFormatFlagsException.java index c498711fa216285aef82feffe94d986748743142..93eaf85b389e2f17cf06358b8dd1fefd851af0a4 100644 --- a/src/java.base/share/classes/java/util/UnknownFormatFlagsException.java +++ b/src/java.base/share/classes/java/util/UnknownFormatFlagsException.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 @@ -34,7 +34,7 @@ package java.util; * * @since 1.5 */ -public class UnknownFormatFlagsException extends IllegalFormatException { +public non-sealed class UnknownFormatFlagsException extends IllegalFormatException { @java.io.Serial private static final long serialVersionUID = 19370506L; 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/concurrent/ThreadLocalRandom.java b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index de8dd5f85809e04b57d4927bb17cb75cc35a5fd6..890d8a0824c9eaa1c8009de5ffac9e43de2a4a5a 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -93,7 +93,7 @@ import jdk.internal.misc.VM; i = 64, j = 0, k = 0, equidistribution = 1 ) -public class ThreadLocalRandom extends Random { +public final class ThreadLocalRandom extends Random { /* * This class implements the java.util.Random API (and subclasses * Random) using a single static instance that accesses 64 bits of 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 f5d4c965b2549771b4f3420f7ba5b403ad800aa6..a06afacc6d2b24bcf023f9c0e7694e8241e82ff6 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -158,7 +158,8 @@ import jdk.internal.util.ArraysSupport; * {@code .} * Any character (may or may not match line terminators) * {@code \d} - * A digit: {@code [0-9]} + * A digit: {@code [0-9]} if + * * UNICODE_CHARACTER_CLASS is not set. See Unicode Support. * {@code \D} * A non-digit: {@code [^0-9]} * {@code \h} @@ -167,7 +168,9 @@ import jdk.internal.util.ArraysSupport; * {@code \H} * A non-horizontal whitespace character: {@code [^\h]} * {@code \s} - * A whitespace character: {@code [ \t\n\x0B\f\r]} + * A whitespace character: {@code [ \t\n\x0B\f\r]} if + * UNICODE_CHARACTER_CLASS is not set. See + * Unicode Support. * {@code \S} * A non-whitespace character: {@code [^\s]} * {@code \v} @@ -176,7 +179,8 @@ import jdk.internal.util.ArraysSupport; * {@code \V} * A non-vertical whitespace character: {@code [^\v]} * {@code \w} - * A word character: {@code [a-zA-Z_0-9]} + * A word character: {@code [a-zA-Z_0-9]} if + * UNICODE_CHARACTER_CLASS is not set. See Unicode Support. * {@code \W} * A non-word character: {@code [^\w]} * @@ -246,11 +250,12 @@ import jdk.internal.util.ArraysSupport; * {@code $} * The end of a line * {@code \b} - * A word boundary + * A word boundary: {@code (?:(?<=\w)(?=\W)|(?<=\W)(?=\w))} (the location + * where a non-word character abuts a word character) * {@code \b{g}} * A Unicode extended grapheme cluster boundary * {@code \B} - * A non-word boundary + * A non-word boundary: {@code [^\b]} * {@code \A} * The beginning of the input * {@code \G} @@ -535,7 +540,7 @@ import jdk.internal.util.ArraysSupport; * that do not capture text and do not count towards the group total, or * named-capturing group. * - *

    Unicode support

    + *

    Unicode support

    * *

    This class is in conformance with Level 1 of Unicode Technical @@ -4005,8 +4010,9 @@ loop: for(int x=0, offset=0; x 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 b89de2cef6276adf5c9251ce169b5f6f4de74a1b..8538b4aef89f4a5582f4f7f2b950f3f47b12bc35 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -1206,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/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java index a6751e886bdbcf26d538534b35ae036b12e662db..e1cb75d54936120c37c827268e7e12f9191b4166 100644 --- a/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/src/java.base/share/classes/javax/crypto/Cipher.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 @@ -1174,7 +1174,7 @@ public class Cipher { } // check if opmode is one of the defined constants - // throw InvalidParameterExeption if not + // throw InvalidParameterException if not private static void checkOpmode(int opmode) { if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) { throw new InvalidParameterException("Invalid operation mode"); diff --git a/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java b/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java index ced87331bce6a6cee895307694e1acef19e4d481..0a86e17cd02a86053298429d00abc0431ae2b8ac 100644 --- a/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java +++ b/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java @@ -29,7 +29,7 @@ import java.security.spec.AlgorithmParameterSpec; /** * This class specifies the parameters used with the - * RC5 + * RC5 * algorithm. * *

    The parameters consist of a version number, a rounds count, a word 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/javax/security/auth/x500/X500Principal.java b/src/java.base/share/classes/javax/security/auth/x500/X500Principal.java index f0bf5e0ae2e1028b2ea07b88bb5c3da511412b06..578249ef48daef7e5108a713b748463c305bad74 100644 --- a/src/java.base/share/classes/javax/security/auth/x500/X500Principal.java +++ b/src/java.base/share/classes/javax/security/auth/x500/X500Principal.java @@ -41,13 +41,13 @@ import sun.security.util.*; * of the distinguished name, or by using the ASN.1 DER encoded byte * representation of the distinguished name. The current specification * for the string representation of a distinguished name is defined in - * RFC 2253: Lightweight + * RFC 2253: Lightweight * Directory Access Protocol (v3): UTF-8 String Representation of * Distinguished Names. This class, however, accepts string formats from - * both RFC 2253 and RFC 1779: + * both RFC 2253 and RFC 1779: * A String Representation of Distinguished Names, and also recognizes * attribute type keywords whose OIDs (Object Identifiers) are defined in - * RFC 5280: Internet X.509 + * RFC 5280: Internet X.509 * Public Key Infrastructure Certificate and CRL Profile. * *

    The string representation for this {@code X500Principal} diff --git a/src/java.base/share/classes/javax/security/auth/x500/package-info.java b/src/java.base/share/classes/javax/security/auth/x500/package-info.java index 38c6439092e4e6e71c5ad7009ed315dcf4b8d545..45859a79bedf03bf81a8ba718c203d28c9e896e4 100644 --- a/src/java.base/share/classes/javax/security/auth/x500/package-info.java +++ b/src/java.base/share/classes/javax/security/auth/x500/package-info.java @@ -31,15 +31,15 @@ *

    Package Specification

    * * 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 972e34e1fd20b94a33ded6d6839f5c727154ba62..35ed4701c9902dbef4ca2fd4f4aa533f7fe28537 100644 --- a/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java +++ b/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java @@ -31,8 +31,8 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Path; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -45,7 +45,7 @@ import java.util.concurrent.ConcurrentHashMap; * 3. No relationship with class loaders. */ public final class RawNativeLibraries { - final Map libraries = new ConcurrentHashMap<>(); + final Set libraries = ConcurrentHashMap.newKeySet(); final Class caller; private RawNativeLibraries(MethodHandles.Lookup trustedCaller) { @@ -70,6 +70,12 @@ public final class RawNativeLibraries { * Load a native library from the given path. Returns null if the given * library is determined to be non-loadable, which is system-dependent. * + * The library is opened with the platform-specific library loading + * mechanism. If this method is called with the same path multiple times, + * the library is opened the same number of times. To close the library + * of the given path, {@code #unload} must be called on all the + * {@code NativeLibrary} instances that load it. + * * @param path the path of the native library */ @SuppressWarnings("removal") @@ -106,28 +112,39 @@ public final class RawNativeLibraries { * NativeLibrary lib = libs.load(System.mapLibraryName("blas")); * } * + * The library is opened with the platform-specific library loading + * mechanism. If this method is called with the same pathname multiple times, + * the library is opened the same number of times. To close the library + * of the given path, {@code #unload} must be called on all the + * {@code NativeLibrary} instances that load it. + * * @param pathname the pathname of the native library * @see System#mapLibraryName(String) */ public NativeLibrary load(String pathname) { - return libraries.computeIfAbsent(pathname, this::get); - } - - private RawNativeLibraryImpl get(String pathname) { - RawNativeLibraryImpl lib = new RawNativeLibraryImpl(caller, pathname); + RawNativeLibraryImpl lib = new RawNativeLibraryImpl(pathname); if (!lib.open()) { return null; } + libraries.add(lib); return lib; } /* - * Unloads the given native library. + * Unloads the given native library. Each {@code NativeLibrary} + * instance can be unloaded only once. + * + * The native library may remain opened after this method is called. + * Refer to the platform-specific library loading mechanism, for example, + * dlopen/dlclose on Unix or LoadLibrary/FreeLibrary on Windows. + * + * @throws IllegalArgumentException if the given library is not + * loaded by this RawNativeLibraries or has already been unloaded */ public void unload(NativeLibrary lib) { Objects.requireNonNull(lib); - if (!libraries.remove(lib.name(), lib)) { - throw new IllegalArgumentException(lib.name() + " not loaded by this RawNativeLibraries instance"); + if (!libraries.remove(lib)) { + throw new IllegalArgumentException("can't unload " + lib.name() + " loaded from " + lib); } RawNativeLibraryImpl nl = (RawNativeLibraryImpl)lib; nl.close(); @@ -139,7 +156,7 @@ public final class RawNativeLibraries { // opaque handle to raw native library, used in native code. long handle; - RawNativeLibraryImpl(Class fromClass, String name) { + RawNativeLibraryImpl(String name) { this.name = name; } 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/misc/CDS.java b/src/java.base/share/classes/jdk/internal/misc/CDS.java index 370086612cd83b8ed4cdf23fc129ee31f5970d32..29b6a3cbce721ba2fd0bd3648d3db6e0ca89200a 100644 --- a/src/java.base/share/classes/jdk/internal/misc/CDS.java +++ b/src/java.base/share/classes/jdk/internal/misc/CDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Stream; -import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; public class CDS { @@ -224,7 +223,7 @@ public class CDS { prt.println(line); } } catch (IOException e) { - throw new RuntimeException("IOExeption happens during drain stream to file " + + throw new RuntimeException("IOException happens during drain stream to file " + fileName + ": " + e.getMessage()); }}).start(); return fileName; diff --git a/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java b/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java index 81064a043e21c138ed8ca4a04eae699e38fb2877..ab28c6339c4b36f69a8b99aa5d2728615ddb09a0 100644 --- a/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java +++ b/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.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 @@ -72,13 +72,15 @@ public final class InnocuousThread extends Thread { */ public static Thread newThread(String name, Runnable target, int priority) { if (System.getSecurityManager() == null) { - return createThread(name, target, ClassLoader.getSystemClassLoader(), priority); + return createThread(name, target, 0L, + ClassLoader.getSystemClassLoader(), priority); } return AccessController.doPrivileged( new PrivilegedAction() { @Override public Thread run() { - return createThread(name, target, ClassLoader.getSystemClassLoader(), priority); + return createThread(name, target, 0L, + ClassLoader.getSystemClassLoader(), priority); } }); } @@ -104,28 +106,50 @@ public final class InnocuousThread extends Thread { */ public static Thread newSystemThread(String name, Runnable target, int priority) { if (System.getSecurityManager() == null) { - return createThread(name, target, null, priority); + return createThread(name, target, 0L, null, priority); } return AccessController.doPrivileged( new PrivilegedAction() { @Override public Thread run() { - return createThread(name, target, null, priority); + return createThread(name, target, 0L, + null, priority); } }); } - private static Thread createThread(String name, Runnable target, ClassLoader loader, int priority) { + /** + * Returns a new InnocuousThread with null context class loader. + * Thread priority is set to the given priority. + */ + public static Thread newSystemThread(String name, Runnable target, + long stackSize, int priority) { + if (System.getSecurityManager() == null) { + return createThread(name, target, stackSize, null, priority); + } + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public Thread run() { + return createThread(name, target, 0L, + null, priority); + } + }); + } + + private static Thread createThread(String name, Runnable target, long stackSize, + ClassLoader loader, int priority) { Thread t = new InnocuousThread(INNOCUOUSTHREADGROUP, - target, name, loader); + target, name, stackSize, loader); if (priority >= 0) { t.setPriority(priority); } return t; } - private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) { - super(group, target, name, 0L, false); + private InnocuousThread(ThreadGroup group, Runnable target, String name, + long stackSize, ClassLoader tccl) { + super(group, target, name, stackSize, false); UNSAFE.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC); UNSAFE.putReferenceRelease(this, CONTEXTCLASSLOADER, tccl); } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java index b5127eb142e5b27de38434552a0eca5fcf33e331..2288378fdddd2aa2346e6664b0fc46e010d7da9b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -98,19 +99,15 @@ public abstract class AnnotationVisitor { * @param annotationVisitor the annotation visitor to which this visitor must delegate method * calls. May be {@literal null}. */ - @SuppressWarnings("deprecation") public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.av = annotationVisitor; } @@ -162,9 +159,9 @@ public abstract class AnnotationVisitor { } /** - * Visits an array value of the annotation. Note that arrays of primitive types (such as byte, + * Visits an array value of the annotation. Note that arrays of primitive values (such as byte, * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit - * visit}. This is what {@link ClassReader} does. + * visit}. This is what {@link ClassReader} does for non empty arrays of primitive values. * * @param name the value name. * @return a visitor to visit the actual array value elements, or {@literal null} if this visitor diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java index 9517d6b02555efe159e75d3d7ae2c6fb2cb6df65..fb4ae268d822f4509216ddcdd6806a8421a5fac5 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -143,7 +144,7 @@ final class AnnotationWriter extends AnnotationVisitor { final boolean useNamedValues, final ByteVector annotation, final AnnotationWriter previousAnnotation) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.symbolTable = symbolTable; this.useNamedValues = useNamedValues; this.annotation = annotation; diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java index daadeb263e20a79db905a3a424059a288e354322..9c5ce91e3ffc43a8d32e2902f56429e707054092 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java index e576513f91bde684a51581a2f0bba3af51c8d89d..9e5b8cf8850d5f1e5fef91c03922b77102355aa6 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -390,3 +391,4 @@ public class ByteVector { data = newData; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index e306e60d45bf209990bd019099ecc8ed605cadcd..7f76419d86c486b002d9daf4352747d8dfed0aad 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; import java.io.ByteArrayOutputStream; @@ -119,6 +120,9 @@ public class ClassReader { */ static final int EXPAND_ASM_INSNS = 256; + /** The maximum size of array to allocate. */ + private static final int MAX_BUFFER_SIZE = 1024 * 1024; + /** The size of the temporary byte array used to read class input streams chunk by chunk. */ private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096; @@ -132,6 +136,9 @@ public class ClassReader { // DontCheck(MemberName): can't be renamed (for backward binary compatibility). public final byte[] b; + /** The offset in bytes of the ClassFile's access_flags field. */ + public final int header; + /** * A byte array containing the JVMS ClassFile structure to be parsed. The content of this array * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally @@ -178,9 +185,6 @@ public class ClassReader { */ private final int maxStringLength; - /** The offset in bytes of the ClassFile's access_flags field. */ - public final int header; - // ----------------------------------------------------------------------------------------------- // Constructors // ----------------------------------------------------------------------------------------------- @@ -341,13 +345,19 @@ public class ClassReader { if (inputStream == null) { throw new IOException("Class not found"); } + int bufferSize = calculateBufferSize(inputStream); try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE]; + byte[] data = new byte[bufferSize]; int bytesRead; - while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) { + int readCount = 0; + while ((bytesRead = inputStream.read(data, 0, bufferSize)) != -1) { outputStream.write(data, 0, bytesRead); + readCount++; } outputStream.flush(); + if (readCount == 1) { + return data; + } return outputStream.toByteArray(); } finally { if (close) { @@ -356,6 +366,20 @@ public class ClassReader { } } + private static int calculateBufferSize(final InputStream inputStream) throws IOException { + int expectedLength = inputStream.available(); + /* + * Some implementations can return 0 while holding available data + * (e.g. new FileInputStream("/proc/a_file")) + * Also in some pathological cases a very small number might be returned, + * and in this case we use default size + */ + if (expectedLength < 256) { + return INPUT_STREAM_DATA_CHUNK_SIZE; + } + return Math.min(expectedLength, MAX_BUFFER_SIZE); + } + // ----------------------------------------------------------------------------------------------- // Accessors // ----------------------------------------------------------------------------------------------- @@ -446,7 +470,6 @@ public class ClassReader { * @param parsingOptions the options to use to parse this class. One or more of {@link * #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}. */ - @SuppressWarnings("deprecation") public void accept( final ClassVisitor classVisitor, final Attribute[] attributePrototypes, @@ -710,11 +733,11 @@ public class ClassReader { // Visit the PermittedSubclasses attribute. if (permittedSubclassesOffset != 0) { int numberOfPermittedSubclasses = readUnsignedShort(permittedSubclassesOffset); - int currentPermittedSubclassOffset = permittedSubclassesOffset + 2; + int currentPermittedSubclassesOffset = permittedSubclassesOffset + 2; while (numberOfPermittedSubclasses-- > 0) { - classVisitor.visitPermittedSubclassExperimental( - readClass(currentPermittedSubclassOffset, charBuffer)); - currentPermittedSubclassOffset += 2; + classVisitor.visitPermittedSubclass( + readClass(currentPermittedSubclassesOffset, charBuffer)); + currentPermittedSubclassesOffset += 2; } } @@ -3005,7 +3028,7 @@ public class ClassReader { // Parse the array_value array. while (numElementValuePairs-- > 0) { currentOffset = - readElementValue(annotationVisitor, currentOffset, /* named = */ null, charBuffer); + readElementValue(annotationVisitor, currentOffset, /* elementName= */ null, charBuffer); } } if (annotationVisitor != null) { @@ -3483,7 +3506,6 @@ public class ClassReader { private int[] readBootstrapMethodsAttribute(final int maxStringLength) { char[] charBuffer = new char[maxStringLength]; int currentAttributeOffset = getFirstAttributeOffset(); - int[] currentBootstrapMethodOffsets = null; for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) { // Read the attribute_info's attribute_name and attribute_length fields. String attributeName = readUTF8(currentAttributeOffset, charBuffer); @@ -3491,17 +3513,17 @@ public class ClassReader { currentAttributeOffset += 6; if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) { // Read the num_bootstrap_methods field and create an array of this size. - currentBootstrapMethodOffsets = new int[readUnsignedShort(currentAttributeOffset)]; + int[] result = new int[readUnsignedShort(currentAttributeOffset)]; // Compute and store the offset of each 'bootstrap_methods' array field entry. int currentBootstrapMethodOffset = currentAttributeOffset + 2; - for (int j = 0; j < currentBootstrapMethodOffsets.length; ++j) { - currentBootstrapMethodOffsets[j] = currentBootstrapMethodOffset; + for (int j = 0; j < result.length; ++j) { + result[j] = currentBootstrapMethodOffset; // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each), // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2). currentBootstrapMethodOffset += 4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2; } - return currentBootstrapMethodOffsets; + return result; } currentAttributeOffset += attributeLength; } @@ -3860,3 +3882,4 @@ public class ClassReader { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassTooLargeException.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassTooLargeException.java index 730cfc953a4be0e53f05145501d52939a8122a33..fe94f7446d497300c5b1fc14ee6ca74625ac42f9 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassTooLargeException.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassTooLargeException.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -100,3 +101,4 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException { return constantPoolCount; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java index 7bfb17051aed692a7f1cfbee8b2300c2f3ff80f5..a19ef8619ad9ea3b4b56225d420ccedc7295105e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java @@ -56,14 +56,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** * A visitor to visit a Java class. The methods of this class must be called in the following order: * {@code visit} [ {@code visitSource} ] [ {@code visitModule} ][ {@code visitNestHost} ][ {@code - * visitPermittedSubclass} ][ {@code visitOuterClass} ] ( {@code visitAnnotation} | {@code - * visitTypeAnnotation} | {@code visitAttribute} )* ( {@code visitNestMember} | {@code - * visitInnerClass} | {@code visitField} | {@code visitMethod} )* {@code visitEnd}. + * visitOuterClass} ] ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code + * visitAttribute} )* ( {@code visitNestMember} | [ {@code * visitPermittedSubclass} ] | {@code + * visitInnerClass} | {@code visitRecordComponent} | {@code visitField} | {@code visitMethod} )* + * {@code visitEnd}. * * @author Eric Bruneton */ @@ -92,24 +94,20 @@ public abstract class ClassVisitor { * Constructs a new {@link ClassVisitor}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param classVisitor the class visitor to which this visitor must delegate method calls. May be * null. */ - @SuppressWarnings("deprecation") public ClassVisitor(final int api, final ClassVisitor classVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.cv = classVisitor; } @@ -172,7 +170,7 @@ public abstract class ClassVisitor { */ public ModuleVisitor visitModule(final String name, final int access, final String version) { if (api < Opcodes.ASM6) { - throw new UnsupportedOperationException("This feature requires ASM6"); + throw new UnsupportedOperationException("Module requires ASM6"); } if (cv != null) { return cv.visitModule(name, access, version); @@ -192,7 +190,7 @@ public abstract class ClassVisitor { */ public void visitNestHost(final String nestHost) { if (api < Opcodes.ASM7) { - throw new UnsupportedOperationException("This feature requires ASM7"); + throw new UnsupportedOperationException("NestHost requires ASM7"); } if (cv != null) { cv.visitNestHost(nestHost); @@ -248,7 +246,7 @@ public abstract class ClassVisitor { public AnnotationVisitor visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { if (api < Opcodes.ASM5) { - throw new UnsupportedOperationException("This feature requires ASM5"); + throw new UnsupportedOperationException("TypeAnnotation requires ASM5"); } if (cv != null) { return cv.visitTypeAnnotation(typeRef, typePath, descriptor, visible); @@ -278,7 +276,7 @@ public abstract class ClassVisitor { */ public void visitNestMember(final String nestMember) { if (api < Opcodes.ASM7) { - throw new UnsupportedOperationException("This feature requires ASM7"); + throw new UnsupportedOperationException("NestMember requires ASM7"); } if (cv != null) { cv.visitNestMember(nestMember); @@ -286,20 +284,17 @@ public abstract class ClassVisitor { } /** - * Experimental, use at your own risk. This method will be renamed when it becomes stable, this - * will break existing code using it. Visits a permitted subclass. A permitted subclass is one - * of the allowed subclasses of the current class. + * Visits a permitted subclasses. A permitted subclass is one of the allowed subclasses of the + * current class. * * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. */ - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { - if (api != Opcodes.ASM9_EXPERIMENTAL) { - throw new UnsupportedOperationException("This feature requires ASM9_EXPERIMENTAL"); + public void visitPermittedSubclass(final String permittedSubclass) { + if (api < Opcodes.ASM9) { + throw new UnsupportedOperationException("PermittedSubclasses requires ASM9"); } if (cv != null) { - cv.visitPermittedSubclassExperimental(permittedSubclass); + cv.visitPermittedSubclass(permittedSubclass); } } @@ -335,7 +330,7 @@ public abstract class ClassVisitor { public RecordComponentVisitor visitRecordComponent( final String name, final String descriptor, final String signature) { if (api < Opcodes.ASM8) { - throw new UnsupportedOperationException("This feature requires ASM8"); + throw new UnsupportedOperationException("Record requires ASM8"); } if (cv != null) { return cv.visitRecordComponent(name, descriptor, signature); @@ -411,3 +406,4 @@ public abstract class ClassVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java index 31cfe85afe29579930ca2a2af8717c2da4b8e67b..7c387666262beb3378b81fcf64b158425494a290 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -110,7 +111,7 @@ public class ClassWriter extends ClassVisitor { /** * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific - * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {}@link Opcodes#ACC_RECORD}, which are + * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {@link Opcodes#ACC_RECORD}, which are * removed when generating the ClassFile structure. */ private int accessFlags; @@ -209,10 +210,10 @@ public class ClassWriter extends ClassVisitor { private ByteVector nestMemberClasses; /** The number_of_classes field of the PermittedSubclasses attribute, or 0. */ - private int numberOfPermittedSubclassClasses; + private int numberOfPermittedSubclasses; /** The 'classes' array of the PermittedSubclasses attribute, or {@literal null}. */ - private ByteVector permittedSubclassClasses; + private ByteVector permittedSubclasses; /** * The record components of this class, stored in a linked list of {@link RecordComponentWriter} @@ -285,7 +286,7 @@ public class ClassWriter extends ClassVisitor { * maximum stack size nor the stack frames will be computed for these methods. */ public ClassWriter(final ClassReader classReader, final int flags) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader); if ((flags & COMPUTE_FRAMES) != 0) { this.compute = MethodWriter.COMPUTE_ALL_FRAMES; @@ -403,20 +404,13 @@ public class ClassWriter extends ClassVisitor { nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index); } - /** - * Experimental, use at your own risk. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public final void visitPermittedSubclassExperimental(final String permittedSubclass) { - if (permittedSubclassClasses == null) { - permittedSubclassClasses = new ByteVector(); + public final void visitPermittedSubclass(final String permittedSubclass) { + if (permittedSubclasses == null) { + permittedSubclasses = new ByteVector(); } - ++numberOfPermittedSubclassClasses; - permittedSubclassClasses.putShort(symbolTable.addConstantClass(permittedSubclass).index); + ++numberOfPermittedSubclasses; + permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index); } @Override @@ -607,9 +601,9 @@ public class ClassWriter extends ClassVisitor { size += 8 + nestMemberClasses.length; symbolTable.addConstantUtf8(Constants.NEST_MEMBERS); } - if (permittedSubclassClasses != null) { + if (permittedSubclasses != null) { ++attributesCount; - size += 8 + permittedSubclassClasses.length; + size += 8 + permittedSubclasses.length; symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES); } int recordComponentCount = 0; @@ -729,12 +723,12 @@ public class ClassWriter extends ClassVisitor { .putShort(numberOfNestMemberClasses) .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length); } - if (permittedSubclassClasses != null) { + if (permittedSubclasses != null) { result .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES)) - .putInt(permittedSubclassClasses.length + 2) - .putShort(numberOfPermittedSubclassClasses) - .putByteArray(permittedSubclassClasses.data, 0, permittedSubclassClasses.length); + .putInt(permittedSubclasses.length + 2) + .putShort(numberOfPermittedSubclasses) + .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length); } if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { result @@ -783,8 +777,8 @@ public class ClassWriter extends ClassVisitor { nestHostClassIndex = 0; numberOfNestMemberClasses = 0; nestMemberClasses = null; - numberOfPermittedSubclassClasses = 0; - permittedSubclassClasses = null; + numberOfPermittedSubclasses = 0; + permittedSubclasses = null; firstRecordComponent = null; lastRecordComponent = null; firstAttribute = null; @@ -1089,3 +1083,4 @@ public class ClassWriter extends ClassVisitor { return getClass().getClassLoader(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ConstantDynamic.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ConstantDynamic.java index 089c69b261d087c52c78071eb9a62466f635b826..457bec9c94a0fa127708e20cb1a6fffa440bb935 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ConstantDynamic.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ConstantDynamic.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; import java.util.Arrays; @@ -207,3 +208,4 @@ public final class ConstantDynamic { + Arrays.toString(bootstrapMethodArguments); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java index 8599089459a38508f759308fe1e53d5614e00148..cc10a3cee72afb085e38410f036f1f4f1f9b7513 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; import java.io.DataInputStream; @@ -250,3 +251,4 @@ final class Constants { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Context.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Context.java index d88d22777d4f03c5ac34eb75299d217fa1505e38..9b64452a096aaed1f3df0cb7873b8c373f1aaf3e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Context.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Context.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -165,3 +166,4 @@ final class Context { */ Object[] currentFrameStackTypes; } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java index 7f4351706b133df0c8c7aa24a4feba789872d1f5..32a4544dfd7e0289c9a622a74d493bb884067352 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -84,3 +85,4 @@ final class CurrentFrame extends Frame { copyFrom(successor); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Edge.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Edge.java index 3dc0ae3caf8990212a826774d9a28c823ba4b448..3da370335ffe9d244af9fa0d1b87ce0b041f9fb3 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Edge.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Edge.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -120,3 +121,4 @@ final class Edge { this.nextEdge = nextEdge; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java index 454c57d319102b596244541971c7d4854ead2e6d..235229da644b59ad18932869e91ce5959e320c9b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -69,8 +70,8 @@ public abstract class FieldVisitor { /** * The ASM API version implemented by this visitor. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ protected final int api; @@ -81,8 +82,8 @@ public abstract class FieldVisitor { * Constructs a new {@link FieldVisitor}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ public FieldVisitor(final int api) { this(api, null); @@ -97,19 +98,15 @@ public abstract class FieldVisitor { * @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be * null. */ - @SuppressWarnings("deprecation") public FieldVisitor(final int api, final FieldVisitor fieldVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.fv = fieldVisitor; } @@ -174,3 +171,4 @@ public abstract class FieldVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java index ef8c52e02f1351c0b8c530928324d7e4c8db97c2..dd3b445056d80b27e46fbc1577316d39a384caaa 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -155,7 +156,7 @@ final class FieldWriter extends FieldVisitor { final String descriptor, final String signature, final Object constantValue) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.symbolTable = symbolTable; this.accessFlags = access; this.nameIndex = symbolTable.addConstantUtf8(name); @@ -313,3 +314,4 @@ final class FieldWriter extends FieldVisitor { attributePrototypes.addAttributes(firstAttribute); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java index 47aa6d5753dd1e97123dd1d975d4defcdf2e8bc4..e4c9b420747ac9f1f8c93553029a754bcae45f23 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -1502,3 +1503,4 @@ class Frame { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java index c18d6142a0d3d956f2c167e3047da494490cdd36..991fc6aabf588502daa6fac710e4481e1ded8887 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -217,3 +218,4 @@ public final class Handle { return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')'; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handler.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handler.java index 3802f67564399d3fab0ff384ff913a5dc091f1c3..848a6d1e14c375194c2349b68a6b89b50771cfe6 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handler.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handler.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -227,3 +228,4 @@ final class Handler { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java index 4f1cedaad2396aa40bd5421b5519d5a86c40092f..a24413f76635cd609bb721f718773c7f166e641f 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -651,3 +652,4 @@ public class Label { return "L" + System.identityHashCode(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodTooLargeException.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodTooLargeException.java index 82a551a3e3d47e641aeb4beb002e2416f0acf0d1..6c7252e35fb3db60c92e85bd9209c9120823c5fa 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodTooLargeException.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodTooLargeException.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -128,3 +129,4 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException { return codeSize; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java index 6bc37b1ec7af94b7caf877cf87c9c4cb998c925f..69939c660010f44fc0870fd406e7f70c5424b1fc 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -110,19 +111,15 @@ public abstract class MethodVisitor { * @param methodVisitor the method visitor to which this visitor must delegate method calls. May * be null. */ - @SuppressWarnings("deprecation") public MethodVisitor(final int api, final MethodVisitor methodVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.mv = methodVisitor; } @@ -815,3 +812,4 @@ public abstract class MethodVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java index 648d523ba95adeae090bd8def7884de2a29be825..155d8fc06b1d8ddb7ce691503656148fdcaa36d2 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -623,7 +624,7 @@ final class MethodWriter extends MethodVisitor { final String signature, final String[] exceptions, final int compute) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.symbolTable = symbolTable; this.accessFlags = "".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access; this.nameIndex = symbolTable.addConstantUtf8(name); @@ -2422,3 +2423,4 @@ final class MethodWriter extends MethodVisitor { attributePrototypes.addAttributes(firstCodeAttribute); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java index 7ae90f18533b54ea62c0d0aaf5d7d188234cdb02..c230852922584b6e5c89b250b206912452e71536 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -96,19 +97,15 @@ public abstract class ModuleVisitor { * @param moduleVisitor the module visitor to which this visitor must delegate method calls. May * be null. */ - @SuppressWarnings("deprecation") public ModuleVisitor(final int api, final ModuleVisitor moduleVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.mv = moduleVisitor; } @@ -214,3 +211,4 @@ public abstract class ModuleVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java index 950b53ee20f3707c8f1331c03c1c4eff086d1f0a..8680488d7a0e0877dddd3f6c951a9a37990ce0c8 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -125,7 +126,7 @@ final class ModuleWriter extends ModuleVisitor { private int mainClassIndex; ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.symbolTable = symbolTable; this.moduleNameIndex = name; this.moduleFlags = access; @@ -282,3 +283,4 @@ final class ModuleWriter extends ModuleVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index d1b6d52865cca24e5ed7d767f8789e1038b69c39..4123d87cd3582124b82c99ae75065c9a4a19ef45 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -79,14 +80,7 @@ public interface Opcodes { int ASM6 = 6 << 16 | 0 << 8; int ASM7 = 7 << 16 | 0 << 8; int ASM8 = 8 << 16 | 0 << 8; - - /** - * Experimental, use at your own risk. This field will be renamed when it becomes stable, this - * will break existing code using it. Only code compiled with --enable-preview can use this. - * - * @deprecated This API is experimental. - */ - @Deprecated int ASM9_EXPERIMENTAL = 1 << 24 | 9 << 16 | 0 << 8; + int ASM9 = 9 << 16 | 0 << 8; /* * Internal flags used to redirect calls to deprecated methods. For instance, if a visitOldStuff @@ -163,7 +157,7 @@ public interface Opcodes { *
           * public class StuffVisitor {
           *   @Deprecated public void visitOldStuff(int arg, ...) {
    -      *     visitNewStuf(arg | SOURCE_DEPRECATED, ...);
    +      *     visitNewStuff(arg | SOURCE_DEPRECATED, ...);
           *   }
           *   public void visitNewStuff(int argAndSource...) {
           *     if ((argAndSource & SOURCE_DEPRECATED) == 0) {
    @@ -185,7 +179,7 @@ public interface Opcodes {
           * 

    and there are two cases: * *

      - *
    • call visitOldSuff: in the call to super.visitOldStuff, the source is set to + *
    • call visitOldStuff: in the call to super.visitOldStuff, the source is set to * SOURCE_DEPRECATED and visitNewStuff is called. Here 'do stuff' is run because the source * was previously set to SOURCE_DEPRECATED, and execution eventually returns to * UserStuffVisitor.visitOldStuff, where 'do user stuff' is run. @@ -590,3 +584,4 @@ public interface Opcodes { int IFNULL = 198; // visitJumpInsn int IFNONNULL = 199; // - } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentVisitor.java index 70396a6cfb934af73588207069bde41db6e13de7..dbca79f4a136b21c1b108b764ded4b17c61cfac1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -68,8 +69,8 @@ package jdk.internal.org.objectweb.asm; */ public abstract class RecordComponentVisitor { /** - * The ASM API version implemented by this visitor. The value of this field must be {@link - * Opcodes#ASM8}. + * The ASM API version implemented by this visitor. The value of this field must be one of {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ protected final int api; @@ -81,7 +82,8 @@ public abstract class RecordComponentVisitor { /** * Constructs a new {@link RecordComponentVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM8}. + * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM8} + * or {@link Opcodes#ASM9}. */ public RecordComponentVisitor(final int api) { this(api, null); @@ -94,20 +96,16 @@ public abstract class RecordComponentVisitor { * @param recordComponentVisitor the record component visitor to which this visitor must delegate * method calls. May be null. */ - @SuppressWarnings("deprecation") public RecordComponentVisitor( final int api, final RecordComponentVisitor recordComponentVisitor) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } - if (api == Opcodes.ASM9_EXPERIMENTAL) { - Constants.checkAsmExperimental(this); - } this.api = api; this.delegate = recordComponentVisitor; } @@ -180,3 +178,4 @@ public abstract class RecordComponentVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentWriter.java index 5ec88b4000a06eda403075f03e1b92017097daae..c75130736af8f6c5603dfad1a44eeb17e068bb82 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/RecordComponentWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; final class RecordComponentWriter extends RecordComponentVisitor { @@ -125,7 +126,7 @@ final class RecordComponentWriter extends RecordComponentVisitor { final String name, final String descriptor, final String signature) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.symbolTable = symbolTable; this.nameIndex = symbolTable.addConstantUtf8(name); this.descriptorIndex = symbolTable.addConstantUtf8(descriptor); @@ -254,3 +255,4 @@ final class RecordComponentWriter extends RecordComponentVisitor { attributePrototypes.addAttributes(firstAttribute); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Symbol.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Symbol.java index 630afc5d0842edf47638ecd932941fc3c5da860a..a6b17c650afb13611515e09419e84fc8fa533238 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Symbol.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Symbol.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -272,3 +273,4 @@ abstract class Symbol { return info; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/SymbolTable.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/SymbolTable.java index d4af66c210197d06930133baa1e4f9b2df69e261..2ca923859f4a195ba5d7a20590f05948c92959c3 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/SymbolTable.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/SymbolTable.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -1351,3 +1352,4 @@ final class SymbolTable { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java index 0302df589e646baa375dccd4d7593084fe1e1d9e..3eaa0c5438094c10806b7cd654b9487a0fccdcdc 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; import java.lang.reflect.Constructor; @@ -924,3 +925,4 @@ public final class Type { return getDescriptor(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java index ae588db91a5ca3bcb80729e9c78a0a40c125129a..9725e5b04488ee439f1b31199653901731d60d78 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -229,3 +230,4 @@ public final class TypePath { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java index bc8da0604a37686fbce0acea0c87132b15230bd3..92a1c94eb0fe94e99129fb2d8113567e949c9d2c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm; /** @@ -464,3 +465,4 @@ public class TypeReference { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java index b34d5cc4bbbf4ca2b7978606f30abe1654d2493a..f319c79456b11d0512c8e212fa060c6624a576e8 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.ArrayList; @@ -185,10 +186,12 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes throw new IllegalArgumentException("Invalid return in constructor"); case RETURN: // empty stack onMethodExit(opcode); + endConstructorBasicBlockWithoutSuccessor(); break; case ATHROW: // 1 before n/a after popValue(); onMethodExit(opcode); + endConstructorBasicBlockWithoutSuccessor(); break; case NOP: case LALOAD: // remove 2 add 2 @@ -383,6 +386,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes popValue(); break; case RET: + endConstructorBasicBlockWithoutSuccessor(); break; default: throw new IllegalArgumentException(INVALID_OPCODE + opcode); @@ -484,10 +488,10 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface); int opcode = opcodeAndSource & ~Opcodes.SOURCE_MASK; - doVisitMethodInsn(opcode, descriptor); + doVisitMethodInsn(opcode, name, descriptor); } - private void doVisitMethodInsn(final int opcode, final String descriptor) { + private void doVisitMethodInsn(final int opcode, final String name, final String descriptor) { if (isConstructor && !superClassConstructorCalled) { for (Type argumentType : Type.getArgumentTypes(descriptor)) { popValue(); @@ -502,7 +506,9 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes break; case INVOKESPECIAL: Object value = popValue(); - if (value == UNINITIALIZED_THIS && !superClassConstructorCalled) { + if (value == UNINITIALIZED_THIS + && !superClassConstructorCalled + && name.equals("")) { superClassConstructorCalled = true; onMethodEnter(); } @@ -528,7 +534,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments) { super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); - doVisitMethodInsn(Opcodes.INVOKEDYNAMIC, descriptor); + doVisitMethodInsn(Opcodes.INVOKEDYNAMIC, name, descriptor); } @Override @@ -560,6 +566,9 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes case JSR: pushValue(OTHER); break; + case GOTO: + endConstructorBasicBlockWithoutSuccessor(); + break; default: break; } @@ -573,6 +582,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes if (isConstructor && !superClassConstructorCalled) { popValue(); addForwardJumps(dflt, labels); + endConstructorBasicBlockWithoutSuccessor(); } } @@ -583,6 +593,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes if (isConstructor && !superClassConstructorCalled) { popValue(); addForwardJumps(dflt, labels); + endConstructorBasicBlockWithoutSuccessor(); } } @@ -619,6 +630,19 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes forwardJumpStackFrames.put(label, new ArrayList<>(stackFrame)); } + private void endConstructorBasicBlockWithoutSuccessor() { + // The next instruction is not reachable from this instruction. If it is dead code, we + // should not try to simulate stack operations, and there is no need to insert advices + // here. If it is reachable with a backward jump, the only possible case is that the super + // class constructor has already been called (backward jumps are forbidden before it is + // called). If it is reachable with a forward jump, there are two sub-cases. Either the + // super class constructor has already been called when reaching the next instruction, or + // it has not been called. But in this case there must be a forwardJumpStackFrames entry + // for a Label designating the next instruction, and superClassConstructorCalled will be + // reset to false there. We can therefore always reset this field to true here. + superClassConstructorCalled = true; + } + private Object popValue() { return stackFrame.remove(stackFrame.size() - 1); } @@ -676,3 +700,4 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes */ protected void onMethodExit(final int opcode) {} } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java index 488764a65ed4a91b9ffeb5231071af0ed68e7d0a..9d0c104fa64872b5b6945373d3a73446fb2036b1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.ArrayList; @@ -147,7 +148,7 @@ public class AnalyzerAdapter extends MethodVisitor { final String name, final String descriptor, final MethodVisitor methodVisitor) { - this(/* latest api = */ Opcodes.ASM8, owner, access, name, descriptor, methodVisitor); + this(/* latest api = */ Opcodes.ASM9, owner, access, name, descriptor, methodVisitor); if (getClass() != AnalyzerAdapter.class) { throw new IllegalStateException(); } @@ -157,8 +158,8 @@ public class AnalyzerAdapter extends MethodVisitor { * Constructs a new {@link AnalyzerAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param owner the owner's class name. * @param access the method's access flags (see {@link Opcodes}). * @param name the method's name. @@ -938,3 +939,4 @@ public class AnalyzerAdapter extends MethodVisitor { labels = null; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java index 937b42f560e13dade9328d7712913d9d86300692..4cadba8cdf12c3d4dad4677fe9e0318a09d56129 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -68,6 +69,12 @@ import jdk.internal.org.objectweb.asm.Opcodes; */ public class AnnotationRemapper extends AnnotationVisitor { + /** + * The descriptor of the visited annotation. May be {@literal null}, for instance for + * AnnotationDefault. + */ + protected final String descriptor; + /** The remapper used to remap the types in the visited annotation. */ protected final Remapper remapper; @@ -75,11 +82,27 @@ public class AnnotationRemapper extends AnnotationVisitor { * Constructs a new {@link AnnotationRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #AnnotationRemapper(int,AnnotationVisitor,Remapper)} version. * - * @param annotationVisitor the annotation visitor this remapper must deleted to. + * @param annotationVisitor the annotation visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited annotation. + * @deprecated use {@link #AnnotationRemapper(String, AnnotationVisitor, Remapper)} instead. */ + @Deprecated public AnnotationRemapper(final AnnotationVisitor annotationVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, annotationVisitor, remapper); + this(/* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new {@link AnnotationRemapper}. Subclasses must not use this constructor. + * Instead, they must use the {@link #AnnotationRemapper(int,String,AnnotationVisitor,Remapper)} + * version. + * + * @param descriptor the descriptor of the visited annotation. May be {@literal null}. + * @param annotationVisitor the annotation visitor this remapper must delegate to. + * @param remapper the remapper to use to remap the types in the visited annotation. + */ + public AnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor, final Remapper remapper) { + this(/* latest api = */ Opcodes.ASM9, descriptor, annotationVisitor, remapper); } /** @@ -87,44 +110,71 @@ public class AnnotationRemapper extends AnnotationVisitor { * * @param api the ASM API version supported by this remapper. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8} - * @param annotationVisitor the annotation visitor this remapper must deleted to. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param annotationVisitor the annotation visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited annotation. + * @deprecated use {@link #AnnotationRemapper(int, String, AnnotationVisitor, Remapper)} instead. */ + @Deprecated protected AnnotationRemapper( final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) { + this(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new {@link AnnotationRemapper}. + * + * @param api the ASM API version supported by this remapper. Must be one of {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param descriptor the descriptor of the visited annotation. May be {@literal null}. + * @param annotationVisitor the annotation visitor this remapper must delegate to. + * @param remapper the remapper to use to remap the types in the visited annotation. + */ + protected AnnotationRemapper( + final int api, + final String descriptor, + final AnnotationVisitor annotationVisitor, + final Remapper remapper) { super(api, annotationVisitor); + this.descriptor = descriptor; this.remapper = remapper; } @Override public void visit(final String name, final Object value) { - super.visit(name, remapper.mapValue(value)); + super.visit(mapAnnotationAttributeName(name), remapper.mapValue(value)); } @Override public void visitEnum(final String name, final String descriptor, final String value) { - super.visitEnum(name, remapper.mapDesc(descriptor), value); + super.visitEnum(mapAnnotationAttributeName(name), remapper.mapDesc(descriptor), value); } @Override public AnnotationVisitor visitAnnotation(final String name, final String descriptor) { - AnnotationVisitor annotationVisitor = super.visitAnnotation(name, remapper.mapDesc(descriptor)); + AnnotationVisitor annotationVisitor = + super.visitAnnotation(mapAnnotationAttributeName(name), remapper.mapDesc(descriptor)); if (annotationVisitor == null) { return null; } else { - return annotationVisitor == av ? this : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == av + ? this + : createAnnotationRemapper(descriptor, annotationVisitor); } } @Override public AnnotationVisitor visitArray(final String name) { - AnnotationVisitor annotationVisitor = super.visitArray(name); + AnnotationVisitor annotationVisitor = super.visitArray(mapAnnotationAttributeName(name)); if (annotationVisitor == null) { return null; } else { - return annotationVisitor == av ? this : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == av + ? this + : createAnnotationRemapper(/* descriptor = */ null, annotationVisitor); } } @@ -134,8 +184,63 @@ public class AnnotationRemapper extends AnnotationVisitor { * * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. * @return the newly created remapper. + * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. */ + @Deprecated protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { - return new AnnotationRemapper(api, annotationVisitor, remapper); + return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new remapper for annotations. The default implementation of this method returns a + * new {@link AnnotationRemapper}. + * + * @param descriptor the descriptor of the visited annotation. + * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. + * @return the newly created remapper. + */ + protected AnnotationVisitor createAnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor) { + return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) + .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); + } + + /** + * Returns either this object, or the given one. If the given object is equal to the object + * returned by the default implementation of the deprecated createAnnotationRemapper method, + * meaning that this method has not been overridden (or only in minor ways, for instance to add + * logging), then we can return this object instead, supposed to have been created by the new + * createAnnotationRemapper method. Otherwise we must return the given object. + * + * @param deprecatedAnnotationVisitor the result of a call to the deprecated + * createAnnotationRemapper method. + * @return either this object, or the given one. + */ + final AnnotationVisitor orDeprecatedValue(final AnnotationVisitor deprecatedAnnotationVisitor) { + if (deprecatedAnnotationVisitor.getClass() == getClass()) { + AnnotationRemapper deprecatedAnnotationRemapper = + (AnnotationRemapper) deprecatedAnnotationVisitor; + if (deprecatedAnnotationRemapper.api == api + && deprecatedAnnotationRemapper.av == av + && deprecatedAnnotationRemapper.remapper == remapper) { + return this; + } + } + return deprecatedAnnotationVisitor; + } + + /** + * Maps an annotation attribute name with the remapper. Returns the original name unchanged if the + * internal name of the annotation is {@literal null}. + * + * @param name the name of the annotation attribute. + * @return the new name of the annotation attribute. + */ + private String mapAnnotationAttributeName(final String name) { + if (descriptor == null) { + return name; + } + return remapper.mapAnnotationAttributeName(descriptor, name); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java index acbf406b8a45135edb8aab123208aef9a34c03e8..29f6c8de1c3f15321a754f93d8279cbba2083261 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.List; @@ -100,11 +101,11 @@ public class ClassRemapper extends ClassVisitor { * Constructs a new {@link ClassRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #ClassRemapper(int,ClassVisitor,Remapper)} version. * - * @param classVisitor the class visitor this remapper must deleted to. + * @param classVisitor the class visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited class. */ public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, classVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, classVisitor, remapper); } /** @@ -112,9 +113,9 @@ public class ClassRemapper extends ClassVisitor { * * @param api the ASM API version supported by this remapper. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. - * @param classVisitor the class visitor this remapper must deleted to. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param classVisitor the class visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited class. */ protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) { @@ -150,7 +151,9 @@ public class ClassRemapper extends ClassVisitor { public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitAnnotation(remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -158,7 +161,9 @@ public class ClassRemapper extends ClassVisitor { final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -249,16 +254,9 @@ public class ClassRemapper extends ClassVisitor { super.visitNestMember(remapper.mapType(nestMember)); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { - super.visitPermittedSubclassExperimental(remapper.mapType(permittedSubclass)); + public void visitPermittedSubclass(final String permittedSubclass) { + super.visitPermittedSubclass(remapper.mapType(permittedSubclass)); } /** @@ -289,9 +287,25 @@ public class ClassRemapper extends ClassVisitor { * * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. * @return the newly created remapper. + * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. */ + @Deprecated protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { - return new AnnotationRemapper(api, annotationVisitor, remapper); + return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new remapper for annotations. The default implementation of this method returns a + * new {@link AnnotationRemapper}. + * + * @param descriptor the descriptor of the visited annotation. + * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. + * @return the newly created remapper. + */ + protected AnnotationVisitor createAnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor) { + return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) + .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); } /** @@ -317,3 +331,4 @@ public class ClassRemapper extends ClassVisitor { return new RecordComponentRemapper(api, recordComponentVisitor, remapper); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java index 64595f3dace0ea8a2b97ea6737c187a84bcea842..dd9abb7e0bd9f338d343dba9ec60fd9e5ec75df2 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.ConstantDynamic; @@ -78,7 +79,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { private int maxSize; public CodeSizeEvaluator(final MethodVisitor methodVisitor) { - this(/* latest api = */ Opcodes.ASM8, methodVisitor); + this(/* latest api = */ Opcodes.ASM9, methodVisitor); } protected CodeSizeEvaluator(final int api, final MethodVisitor methodVisitor) { @@ -236,3 +237,4 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { super.visitMultiANewArrayInsn(descriptor, numDimensions); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java index 54fea2e7720380ec79f57f638b0164b48c67354b..5f4f10a86d131d4ca0cc1e11fb123dbcf724dc57 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -77,20 +78,20 @@ public class FieldRemapper extends FieldVisitor { * Constructs a new {@link FieldRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #FieldRemapper(int,FieldVisitor,Remapper)} version. * - * @param fieldVisitor the field visitor this remapper must deleted to. + * @param fieldVisitor the field visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited field. */ public FieldRemapper(final FieldVisitor fieldVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, fieldVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, fieldVisitor, remapper); } /** * Constructs a new {@link FieldRemapper}. * - * @param api the ASM API version supported by this remapper. Must be one of {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link Opcodes#ASM8}. - * @param fieldVisitor the field visitor this remapper must deleted to. + * @param api the ASM API version supported by this remapper. Must be one of {@link Opcodes#ASM4}, + * {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8}, or + * {@link Opcodes#ASM9}. + * @param fieldVisitor the field visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited field. */ protected FieldRemapper(final int api, final FieldVisitor fieldVisitor, final Remapper remapper) { @@ -102,7 +103,9 @@ public class FieldRemapper extends FieldVisitor { public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitAnnotation(remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -110,7 +113,9 @@ public class FieldRemapper extends FieldVisitor { final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } /** @@ -119,8 +124,25 @@ public class FieldRemapper extends FieldVisitor { * * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. * @return the newly created remapper. + * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. */ + @Deprecated protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { - return new AnnotationRemapper(api, annotationVisitor, remapper); + return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new remapper for annotations. The default implementation of this method returns a + * new {@link AnnotationRemapper}. + * + * @param descriptor the descriptor of the visited annotation. + * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. + * @return the newly created remapper. + */ + protected AnnotationVisitor createAnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor) { + return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) + .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java index 1a18fc5550ea1674d03286e02752c47abf9ebbf0..fa9d8ad593b1de4ba912a378e3c48c233b9a7870 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.ArrayList; @@ -232,7 +233,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { final int access, final String name, final String descriptor) { - this(/* latest api = */ Opcodes.ASM8, methodVisitor, access, name, descriptor); + this(/* latest api = */ Opcodes.ASM9, methodVisitor, access, name, descriptor); if (getClass() != GeneratorAdapter.class) { throw new IllegalStateException(); } @@ -242,8 +243,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Constructs a new {@link GeneratorAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param methodVisitor the method visitor to which this adapter delegates calls. * @param access the method's access flags (see {@link Opcodes}). * @param name the method's name. @@ -1398,3 +1399,4 @@ public class GeneratorAdapter extends LocalVariablesSorter { mark(catchLabel); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java index ba150bf85830380975ce70922b81fc79cadab709..1e1f30d5db797524d33d8f688fcc5faf659b1ae7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.ConstantDynamic; @@ -83,7 +84,7 @@ public class InstructionAdapter extends MethodVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public InstructionAdapter(final MethodVisitor methodVisitor) { - this(/* latest api = */ Opcodes.ASM8, methodVisitor); + this(/* latest api = */ Opcodes.ASM9, methodVisitor); if (getClass() != InstructionAdapter.class) { throw new IllegalStateException(); } @@ -93,8 +94,8 @@ public class InstructionAdapter extends MethodVisitor { * Constructs a new {@link InstructionAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param methodVisitor the method visitor to which this adapter delegates calls. */ protected InstructionAdapter(final int api, final MethodVisitor methodVisitor) { @@ -1121,7 +1122,7 @@ public class InstructionAdapter extends MethodVisitor { final String owner, final String name, final String descriptor, final boolean isInterface) { if (api < Opcodes.ASM5) { if (isInterface) { - throw new IllegalArgumentException("INVOKEVIRTUAL on interfaces require ASM 5"); + throw new UnsupportedOperationException("INVOKEVIRTUAL on interfaces require ASM 5"); } invokevirtual(owner, name, descriptor); return; @@ -1159,7 +1160,7 @@ public class InstructionAdapter extends MethodVisitor { final String owner, final String name, final String descriptor, final boolean isInterface) { if (api < Opcodes.ASM5) { if (isInterface) { - throw new IllegalArgumentException("INVOKESPECIAL on interfaces require ASM 5"); + throw new UnsupportedOperationException("INVOKESPECIAL on interfaces require ASM 5"); } invokespecial(owner, name, descriptor); return; @@ -1197,7 +1198,7 @@ public class InstructionAdapter extends MethodVisitor { final String owner, final String name, final String descriptor, final boolean isInterface) { if (api < Opcodes.ASM5) { if (isInterface) { - throw new IllegalArgumentException("INVOKESTATIC on interfaces require ASM 5"); + throw new UnsupportedOperationException("INVOKESTATIC on interfaces require ASM 5"); } invokestatic(owner, name, descriptor); return; @@ -1329,3 +1330,4 @@ public class InstructionAdapter extends MethodVisitor { mv.visitLabel(label); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java index deb08e45ebb76086ffa48c3f105602157cb002e9..7ef4a5108bc3d5f8f167ed7862e1274464d9b1e7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.AbstractMap; @@ -130,7 +131,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { final String signature, final String[] exceptions) { this( - /* latest api = */ Opcodes.ASM8, + /* latest api = */ Opcodes.ASM9, methodVisitor, access, name, @@ -146,8 +147,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * Constructs a new {@link JSRInlinerAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param methodVisitor the method visitor to send the resulting inlined method code to, or * null. * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if @@ -600,3 +601,4 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java index c2df9e3c395864bffb46c300146a95bcce86c852..aab097156c0f444e9495a29905732613c5e52d81 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -112,7 +113,7 @@ public class LocalVariablesSorter extends MethodVisitor { */ public LocalVariablesSorter( final int access, final String descriptor, final MethodVisitor methodVisitor) { - this(/* latest api = */ Opcodes.ASM8, access, descriptor, methodVisitor); + this(/* latest api = */ Opcodes.ASM9, access, descriptor, methodVisitor); if (getClass() != LocalVariablesSorter.class) { throw new IllegalStateException(); } @@ -122,8 +123,8 @@ public class LocalVariablesSorter extends MethodVisitor { * Constructs a new {@link LocalVariablesSorter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param access access flags of the adapted method. * @param descriptor the method's descriptor (see {@link Type}). * @param methodVisitor the method visitor to which this adapter delegates calls. @@ -381,3 +382,4 @@ public class LocalVariablesSorter extends MethodVisitor { return local; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java index 16dc0d8375e068b265a71c4048de427742bf7eef..1fcab96f1813c872cf34032f06a14a96bfa1e453 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.HashMap; @@ -291,3 +292,4 @@ public class Method { return name.hashCode() ^ descriptor.hashCode(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java index 29c4df3c6fc5f0b9bf9545ace0a56ff289ca3729..aaa7d3ffe01d2262718fcaeca8f9b0f1c66f27a6 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -79,21 +80,21 @@ public class MethodRemapper extends MethodVisitor { * Constructs a new {@link MethodRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #MethodRemapper(int,MethodVisitor,Remapper)} version. * - * @param methodVisitor the method visitor this remapper must deleted to. + * @param methodVisitor the method visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited method. */ public MethodRemapper(final MethodVisitor methodVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, methodVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, methodVisitor, remapper); } /** * Constructs a new {@link MethodRemapper}. * * @param api the ASM API version supported by this remapper. Must be one of {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. - * @param methodVisitor the method visitor this remapper must deleted to. + * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param methodVisitor the method visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited method. */ protected MethodRemapper( @@ -107,7 +108,7 @@ public class MethodRemapper extends MethodVisitor { AnnotationVisitor annotationVisitor = super.visitAnnotationDefault(); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(/* descriptor = */ null, annotationVisitor); } @Override @@ -116,7 +117,7 @@ public class MethodRemapper extends MethodVisitor { super.visitAnnotation(remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -126,7 +127,7 @@ public class MethodRemapper extends MethodVisitor { super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -136,7 +137,7 @@ public class MethodRemapper extends MethodVisitor { super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -240,7 +241,7 @@ public class MethodRemapper extends MethodVisitor { super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -256,7 +257,7 @@ public class MethodRemapper extends MethodVisitor { super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -290,7 +291,7 @@ public class MethodRemapper extends MethodVisitor { typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible); return annotationVisitor == null ? annotationVisitor - : createAnnotationRemapper(annotationVisitor); + : createAnnotationRemapper(descriptor, annotationVisitor); } /** @@ -299,8 +300,25 @@ public class MethodRemapper extends MethodVisitor { * * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. * @return the newly created remapper. + * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. */ + @Deprecated protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { - return new AnnotationRemapper(api, annotationVisitor, remapper); + return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new remapper for annotations. The default implementation of this method returns a + * new {@link AnnotationRemapper}. + * + * @param descriptor the descriptor of the visited annotation. + * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. + * @return the newly created remapper. + */ + protected AnnotationVisitor createAnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor) { + return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) + .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java index 8786f195685efa06ca233ef73f9f171cfdb1d394..5b4cc253c39e8b589b05d836118e6916442e33fc 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.ArrayList; @@ -133,7 +134,7 @@ public final class ModuleHashesAttribute extends Attribute { currentOffset += 2; byte[] hash = new byte[hashLength]; for (int j = 0; j < hashLength; ++j) { - hash[j] = (byte) (classReader.readByte(currentOffset) & 0xFF); + hash[j] = (byte) classReader.readByte(currentOffset); currentOffset += 1; } hashList.add(hash); @@ -167,3 +168,4 @@ public final class ModuleHashesAttribute extends Attribute { return byteVector; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java index fdfc7c48207d95bec867be10f8377e0f710812a5..f04e2f0322e059736fd91db2b551d2bec6d7dd5f 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.ModuleVisitor; @@ -75,11 +76,11 @@ public class ModuleRemapper extends ModuleVisitor { * Constructs a new {@link ModuleRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #ModuleRemapper(int,ModuleVisitor,Remapper)} version. * - * @param moduleVisitor the module visitor this remapper must deleted to. + * @param moduleVisitor the module visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited module. */ public ModuleRemapper(final ModuleVisitor moduleVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, moduleVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, moduleVisitor, remapper); } /** @@ -87,9 +88,9 @@ public class ModuleRemapper extends ModuleVisitor { * * @param api the ASM API version supported by this remapper. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. - * @param moduleVisitor the module visitor this remapper must deleted to. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param moduleVisitor the module visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited module. */ protected ModuleRemapper( @@ -151,3 +152,4 @@ public class ModuleRemapper extends ModuleVisitor { super.visitProvide(remapper.mapType(service), remappedProviders); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java index f862ddcce8d0f0422f65e6e9567acc9ab0a8d5f9..8187ad30e0cc7ea6d52b856264a3bca1471c5a5b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.Attribute; @@ -141,3 +142,4 @@ public final class ModuleResolutionAttribute extends Attribute { return byteVector; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java index 998adcf8b42f50fc44f39ca49b8e5ef7bea8ce16..4d92734a972e465ae23e152f68e0b8349c33e0fe 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.Attribute; @@ -115,3 +116,4 @@ public final class ModuleTargetAttribute extends Attribute { return byteVector; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RecordComponentRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RecordComponentRemapper.java index 531a371c5457ae1170d70bcecd849744103ce7ef..6974b05d71e8e0f08fda7a6c107967cc2cf79649 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RecordComponentRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RecordComponentRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -83,14 +84,14 @@ public class RecordComponentRemapper extends RecordComponentVisitor { */ public RecordComponentRemapper( final RecordComponentVisitor recordComponentVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, recordComponentVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, recordComponentVisitor, remapper); } /** * Constructs a new {@link RecordComponentRemapper}. * - * @param api the ASM API version supported by this remapper. Must be {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. + * @param api the ASM API version supported by this remapper. Must be one of {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. * @param recordComponentVisitor the record component visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited record component. */ @@ -104,7 +105,9 @@ public class RecordComponentRemapper extends RecordComponentVisitor { public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitAnnotation(remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } @Override @@ -112,7 +115,9 @@ public class RecordComponentRemapper extends RecordComponentVisitor { final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { AnnotationVisitor annotationVisitor = super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); + return annotationVisitor == null + ? null + : createAnnotationRemapper(descriptor, annotationVisitor); } /** @@ -121,8 +126,25 @@ public class RecordComponentRemapper extends RecordComponentVisitor { * * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. * @return the newly created remapper. + * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. */ + @Deprecated protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { - return new AnnotationRemapper(api, annotationVisitor, remapper); + return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); + } + + /** + * Constructs a new remapper for annotations. The default implementation of this method returns a + * new {@link AnnotationRemapper}. + * + * @param descriptor the descriptor sof the visited annotation. + * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. + * @return the newly created remapper. + */ + protected AnnotationVisitor createAnnotationRemapper( + final String descriptor, final AnnotationVisitor annotationVisitor) { + return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) + .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java index de0e11889cc79b7eeffffca12a89f5a5fed5ae56..0439b4054e27c2f4921254410d631496e800ed36 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.ConstantDynamic; @@ -266,6 +267,18 @@ public abstract class Remapper { return new SignatureRemapper(signatureVisitor, this); } + /** + * Maps an annotation attribute name. The default implementation of this method returns the given + * name, unchanged. Subclasses can override. + * + * @param descriptor the descriptor of the annotation class. + * @param name the name of the annotation attribute. + * @return the new name of the annotation attribute. + */ + public String mapAnnotationAttributeName(final String descriptor, final String name) { + return name; + } + /** * Maps an inner class name to its new name. The default implementation of this method provides a * strategy that will work for inner classes produced by Java, but not necessarily other @@ -376,3 +389,4 @@ public abstract class Remapper { return internalName; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java index 6347464f45532994022f68efd3864560169355b0..0f41cff5354c1fadd18bddbe1a41e47086454254 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java @@ -74,7 +74,7 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor { public RemappingAnnotationAdapter( final AnnotationVisitor annotationVisitor, final Remapper remapper) { - this(Opcodes.ASM6, annotationVisitor, remapper); + this(Opcodes.ASM9, annotationVisitor, remapper); } protected RemappingAnnotationAdapter( @@ -113,3 +113,4 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor { : new RemappingAnnotationAdapter(annotationVisitor, remapper)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java deleted file mode 100644 index 11af9d0d9daa5eb418375ac2674f3ce6b168d91e..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package jdk.internal.org.objectweb.asm.commons; - -import jdk.internal.org.objectweb.asm.AnnotationVisitor; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.FieldVisitor; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.ModuleVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.TypePath; - -/** - * A {@link ClassVisitor} for type remapping. - * - * @deprecated use {@link ClassRemapper} instead. - * @author Eugene Kuleshov - */ -@Deprecated -public class RemappingClassAdapter extends ClassVisitor { - - protected final Remapper remapper; - - protected String className; - - public RemappingClassAdapter(final ClassVisitor classVisitor, final Remapper remapper) { - this(Opcodes.ASM6, classVisitor, remapper); - } - - protected RemappingClassAdapter( - final int api, final ClassVisitor classVisitor, final Remapper remapper) { - super(api, classVisitor); - this.remapper = remapper; - } - - @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) { - this.className = name; - super.visit( - version, - access, - remapper.mapType(name), - remapper.mapSignature(signature, false), - remapper.mapType(superName), - interfaces == null ? null : remapper.mapTypes(interfaces)); - } - - @Override - public ModuleVisitor visitModule(final String name, final int flags, final String version) { - throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead"); - } - - @Override - public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { - AnnotationVisitor annotationVisitor = - super.visitAnnotation(remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor); - } - - @Override - public AnnotationVisitor visitTypeAnnotation( - final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { - AnnotationVisitor annotationVisitor = - super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); - return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor); - } - - @Override - public FieldVisitor visitField( - final int access, - final String name, - final String descriptor, - final String signature, - final Object value) { - FieldVisitor fieldVisitor = - super.visitField( - access, - remapper.mapFieldName(className, name, descriptor), - remapper.mapDesc(descriptor), - remapper.mapSignature(signature, true), - remapper.mapValue(value)); - return fieldVisitor == null ? null : createRemappingFieldAdapter(fieldVisitor); - } - - @Override - public MethodVisitor visitMethod( - final int access, - final String name, - final String descriptor, - final String signature, - final String[] exceptions) { - String newDescriptor = remapper.mapMethodDesc(descriptor); - MethodVisitor methodVisitor = - super.visitMethod( - access, - remapper.mapMethodName(className, name, descriptor), - newDescriptor, - remapper.mapSignature(signature, false), - exceptions == null ? null : remapper.mapTypes(exceptions)); - return methodVisitor == null - ? null - : createRemappingMethodAdapter(access, newDescriptor, methodVisitor); - } - - @Override - public void visitInnerClass( - final String name, final String outerName, final String innerName, final int access) { - super.visitInnerClass( - remapper.mapType(name), - outerName == null ? null : remapper.mapType(outerName), - innerName, - access); - } - - @Override - public void visitOuterClass(final String owner, final String name, final String descriptor) { - super.visitOuterClass( - remapper.mapType(owner), - name == null ? null : remapper.mapMethodName(owner, name, descriptor), - descriptor == null ? null : remapper.mapMethodDesc(descriptor)); - } - - protected FieldVisitor createRemappingFieldAdapter(final FieldVisitor fieldVisitor) { - return new RemappingFieldAdapter(fieldVisitor, remapper); - } - - protected MethodVisitor createRemappingMethodAdapter( - final int access, final String newDescriptor, final MethodVisitor methodVisitior) { - return new RemappingMethodAdapter(access, newDescriptor, methodVisitior, remapper); - } - - protected AnnotationVisitor createRemappingAnnotationAdapter(final AnnotationVisitor av) { - return new RemappingAnnotationAdapter(av, remapper); - } -} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java deleted file mode 100644 index 3fa8ccfb8991ebd2222c3f3c2c8a3b2309bd4543..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package jdk.internal.org.objectweb.asm.commons; - -import jdk.internal.org.objectweb.asm.AnnotationVisitor; -import jdk.internal.org.objectweb.asm.FieldVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.TypePath; - -/** - * A {@link FieldVisitor} adapter for type remapping. - * - * @deprecated use {@link FieldRemapper} instead. - * @author Eugene Kuleshov - */ -@Deprecated -public class RemappingFieldAdapter extends FieldVisitor { - - private final Remapper remapper; - - public RemappingFieldAdapter(final FieldVisitor fieldVisitor, final Remapper remapper) { - this(Opcodes.ASM6, fieldVisitor, remapper); - } - - protected RemappingFieldAdapter( - final int api, final FieldVisitor fieldVisitor, final Remapper remapper) { - super(api, fieldVisitor); - this.remapper = remapper; - } - - @Override - public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { - AnnotationVisitor annotationVisitor = fv.visitAnnotation(remapper.mapDesc(descriptor), visible); - return annotationVisitor == null - ? null - : new RemappingAnnotationAdapter(annotationVisitor, remapper); - } - - @Override - public AnnotationVisitor visitTypeAnnotation( - final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { - AnnotationVisitor annotationVisitor = - super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); - return annotationVisitor == null - ? null - : new RemappingAnnotationAdapter(annotationVisitor, remapper); - } -} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java index e9a4325300444a61a5bb43d7a67605b34a5b9074..68ad22a4793204aa4cef188a034d2c2889cb0efb 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java @@ -81,7 +81,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { final String descriptor, final MethodVisitor methodVisitor, final Remapper remapper) { - this(Opcodes.ASM6, access, descriptor, methodVisitor, remapper); + this(Opcodes.ASM9, access, descriptor, methodVisitor, remapper); } protected RemappingMethodAdapter( @@ -307,3 +307,4 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { : new RemappingAnnotationAdapter(annotationVisitor, remapper); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java deleted file mode 100644 index decfabd49e16fa033593e2792eafa14ca3116224..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package jdk.internal.org.objectweb.asm.commons; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.signature.SignatureVisitor; - -/** - * A {@link SignatureVisitor} adapter for type mapping. - * - * @deprecated use {@link SignatureRemapper} instead. - * @author Eugene Kuleshov - */ -@Deprecated -public class RemappingSignatureAdapter extends SignatureVisitor { - - private final SignatureVisitor signatureVisitor; - - private final Remapper remapper; - - private String className; - - public RemappingSignatureAdapter( - final SignatureVisitor signatureVisitor, final Remapper remapper) { - this(Opcodes.ASM6, signatureVisitor, remapper); - } - - protected RemappingSignatureAdapter( - final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) { - super(api); - this.signatureVisitor = signatureVisitor; - this.remapper = remapper; - } - - @Override - public void visitClassType(final String name) { - className = name; - signatureVisitor.visitClassType(remapper.mapType(name)); - } - - @Override - public void visitInnerClassType(final String name) { - String remappedOuter = remapper.mapType(className) + '$'; - className = className + '$' + name; - String remappedName = remapper.mapType(className); - int index = - remappedName.startsWith(remappedOuter) - ? remappedOuter.length() - : remappedName.lastIndexOf('$') + 1; - signatureVisitor.visitInnerClassType(remappedName.substring(index)); - } - - @Override - public void visitFormalTypeParameter(final String name) { - signatureVisitor.visitFormalTypeParameter(name); - } - - @Override - public void visitTypeVariable(final String name) { - signatureVisitor.visitTypeVariable(name); - } - - @Override - public SignatureVisitor visitArrayType() { - signatureVisitor.visitArrayType(); - return this; - } - - @Override - public void visitBaseType(final char descriptor) { - signatureVisitor.visitBaseType(descriptor); - } - - @Override - public SignatureVisitor visitClassBound() { - signatureVisitor.visitClassBound(); - return this; - } - - @Override - public SignatureVisitor visitExceptionType() { - signatureVisitor.visitExceptionType(); - return this; - } - - @Override - public SignatureVisitor visitInterface() { - signatureVisitor.visitInterface(); - return this; - } - - @Override - public SignatureVisitor visitInterfaceBound() { - signatureVisitor.visitInterfaceBound(); - return this; - } - - @Override - public SignatureVisitor visitParameterType() { - signatureVisitor.visitParameterType(); - return this; - } - - @Override - public SignatureVisitor visitReturnType() { - signatureVisitor.visitReturnType(); - return this; - } - - @Override - public SignatureVisitor visitSuperclass() { - signatureVisitor.visitSuperclass(); - return this; - } - - @Override - public void visitTypeArgument() { - signatureVisitor.visitTypeArgument(); - } - - @Override - public SignatureVisitor visitTypeArgument(final char wildcard) { - signatureVisitor.visitTypeArgument(wildcard); - return this; - } - - @Override - public void visitEnd() { - signatureVisitor.visitEnd(); - } -} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java index 727a5ff3c14b5c8bd043ac441121a24d33340e84..74c7542a2704bf8de19917a02f65dd7b2fcc1e39 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.io.ByteArrayOutputStream; @@ -181,7 +182,7 @@ public class SerialVersionUIDAdder extends ClassVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public SerialVersionUIDAdder(final ClassVisitor classVisitor) { - this(/* latest api = */ Opcodes.ASM8, classVisitor); + this(/* latest api = */ Opcodes.ASM9, classVisitor); if (getClass() != SerialVersionUIDAdder.class) { throw new IllegalStateException(); } @@ -191,8 +192,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { * Constructs a new {@link SerialVersionUIDAdder}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param classVisitor a {@link ClassVisitor} to which this visitor will delegate calls. */ protected SerialVersionUIDAdder(final int api, final ClassVisitor classVisitor) { @@ -349,7 +350,7 @@ public class SerialVersionUIDAdder extends ClassVisitor { } /** - * Adds a static final serialVersionUID field to the class, with the given value. + * Adds a final static serialVersionUID field to the class, with the given value. * * @param svuid the serialVersionUID field value. */ @@ -522,3 +523,4 @@ public class SerialVersionUIDAdder extends ClassVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java index 0de4b5630f03aa632b68cafcf9e02b7d0082ec56..81209e1bd643e6783dcba6ad38715c46c8a40d40 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.ArrayList; @@ -79,11 +80,11 @@ public class SignatureRemapper extends SignatureVisitor { * Constructs a new {@link SignatureRemapper}. Subclasses must not use this constructor. * Instead, they must use the {@link #SignatureRemapper(int,SignatureVisitor,Remapper)} version. * - * @param signatureVisitor the signature visitor this remapper must deleted to. + * @param signatureVisitor the signature visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited signature. */ public SignatureRemapper(final SignatureVisitor signatureVisitor, final Remapper remapper) { - this(/* latest api = */ Opcodes.ASM8, signatureVisitor, remapper); + this(/* latest api = */ Opcodes.ASM9, signatureVisitor, remapper); } /** @@ -91,9 +92,9 @@ public class SignatureRemapper extends SignatureVisitor { * * @param api the ASM API version supported by this remapper. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5},{@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. - * @param signatureVisitor the signature visitor this remapper must deleted to. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. + * @param signatureVisitor the signature visitor this remapper must delegate to. * @param remapper the remapper to use to remap the types in the visited signature. */ protected SignatureRemapper( @@ -203,3 +204,4 @@ public class SignatureRemapper extends SignatureVisitor { classNames.remove(classNames.size() - 1); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java index 3e166379f6b7c6a8f6074a131578275c72d403f0..314738e3b2e94dd7ee9822230dc8ae9b53c79044 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.Collections; @@ -80,8 +81,9 @@ public class SimpleRemapper extends Remapper { * name. *
    • for invokedynamic method names, the key is the name and descriptor of the method (in * the form .<name><descriptor>), and the value is the new method name. - *
    • for field names, the key is the owner and name of the field (in the form - * <owner>.<name>), and the value is the new field name. + *
    • for field and attribute names, the key is the owner and name of the field or + * attribute (in the form <owner>.<name>), and the value is the new field + * name. *
    • for internal names, the key is the old internal name, and the value is the new * internal name. *
    @@ -113,6 +115,12 @@ public class SimpleRemapper extends Remapper { return remappedName == null ? name : remappedName; } + @Override + public String mapAnnotationAttributeName(final String descriptor, final String name) { + String remappedName = map(descriptor + '.' + name); + return remappedName == null ? name : remappedName; + } + @Override public String mapFieldName(final String owner, final String name, final String descriptor) { String remappedName = map(owner + '.' + name); @@ -124,3 +132,4 @@ public class SimpleRemapper extends Remapper { return mapping.get(key); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java index 3d803deb17db6e4358185fc85a1e8befaa0f860a..b92e721a55ec0dc6379cec52c951b9d2f5894563 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.ClassVisitor; @@ -92,15 +93,15 @@ public class StaticInitMerger extends ClassVisitor { * null. */ public StaticInitMerger(final String prefix, final ClassVisitor classVisitor) { - this(/* latest api = */ Opcodes.ASM8, prefix, classVisitor); + this(/* latest api = */ Opcodes.ASM9, prefix, classVisitor); } /** * Constructs a new {@link StaticInitMerger}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param prefix the prefix to use to rename the existing <clinit> methods. * @param classVisitor the class visitor to which this visitor must delegate method calls. May be * null. @@ -154,3 +155,4 @@ public class StaticInitMerger extends ClassVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java index 2eecf0c3c7613f9f834e2f7d7eb01f9b44699d47..69db3287c40963d1b02e37f691b33d06ea91fc55 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.Label; @@ -80,3 +81,4 @@ public interface TableSwitchGenerator { /** Generates the code for the default switch case. */ void generateDefault(); } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java index 61431f190df908e38ab7c4ce7a57af6fafb64666..f64766572d221e58aaecc758a4358f9b276ddd31 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.commons; import java.util.Collections; @@ -101,7 +102,7 @@ public class TryCatchBlockSorter extends MethodNode { final String signature, final String[] exceptions) { this( - /* latest api = */ Opcodes.ASM8, + /* latest api = */ Opcodes.ASM9, methodVisitor, access, name, @@ -154,3 +155,4 @@ public class TryCatchBlockSorter extends MethodNode { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java index 29d451d7045898f58e207e733960537a0e6c4e0c..9870ea5f72bde6012f9c047b14eeaddf59d0a6bc 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.signature; /** @@ -281,3 +282,4 @@ public class SignatureReader { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java index 32600c7d5b4c911055f23fc6468e93e5a77470ca..cbfee22ecd8bb43fdf4f1a7d8410c1023b3a1880 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.signature; import jdk.internal.org.objectweb.asm.Opcodes; @@ -102,14 +103,13 @@ public abstract class SignatureVisitor { * @param api the ASM API version implemented by this visitor. Must be one of {@link * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. */ - @SuppressWarnings("deprecation") public SignatureVisitor(final int api) { - if (api != Opcodes.ASM8 + if (api != Opcodes.ASM9 + && api != Opcodes.ASM8 && api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 - && api != Opcodes.ASM4 - && api != Opcodes.ASM9_EXPERIMENTAL) { + && api != Opcodes.ASM4) { throw new IllegalArgumentException("Unsupported api " + api); } this.api = api; @@ -238,3 +238,4 @@ public abstract class SignatureVisitor { /** Ends the visit of a signature corresponding to a class or interface type. */ public void visitEnd() {} } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java index 68f8b46cb86d4b4c7add8562f455c3e4dc3c7a55..eceaaee424c57d268f1b7651c390804e5c3ab8fd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.signature; import jdk.internal.org.objectweb.asm.Opcodes; @@ -101,7 +102,7 @@ public class SignatureWriter extends SignatureVisitor { /** Constructs a new {@link SignatureWriter}. */ public SignatureWriter() { - super(/* latest api =*/ Opcodes.ASM8); + super(/* latest api =*/ Opcodes.ASM9); } // ----------------------------------------------------------------------------------------------- @@ -269,3 +270,4 @@ public class SignatureWriter extends SignatureVisitor { argumentStack /= 2; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java index 35bfd9bd42376d936ffcee9b0dc39b4770168b4f..28b17cecc2b7f7675c7ef5bd73b0124e76e1c978 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -294,3 +295,4 @@ public abstract class AbstractInsnNode { return this; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java index b18690a667233c370867dd936263608fc3e8f76d..d6e874221f662e1be02aef16c4613e94190a0f2f 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -91,7 +92,7 @@ public class AnnotationNode extends AnnotationVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public AnnotationNode(final String descriptor) { - this(/* latest api = */ Opcodes.ASM8, descriptor); + this(/* latest api = */ Opcodes.ASM9, descriptor); if (getClass() != AnnotationNode.class) { throw new IllegalStateException(); } @@ -101,8 +102,8 @@ public class AnnotationNode extends AnnotationVisitor { * Constructs a new {@link AnnotationNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8} + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param descriptor the class descriptor of the annotation class. */ public AnnotationNode(final int api, final String descriptor) { @@ -116,7 +117,7 @@ public class AnnotationNode extends AnnotationVisitor { * @param values where the visited values must be stored. */ AnnotationNode(final List values) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.values = values; } @@ -205,7 +206,7 @@ public class AnnotationNode extends AnnotationVisitor { * introduced in more recent versions of the ASM API than the given version. * * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5}, - * {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link Opcodes#ASM8}. + * {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8} or {@link Opcodes#ASM9}. */ public void check(final int api) { // nothing to do @@ -260,3 +261,4 @@ public class AnnotationNode extends AnnotationVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java index 1f12a83b639deef86f2a8174c86cb5dec4f5a03e..56bfc584b1a52b361f02d7e793b09fb8a4abdcfd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -158,14 +159,8 @@ public class ClassNode extends ClassVisitor { /** The internal names of the nest members of this class. May be {@literal null}. */ public List nestMembers; - /** - * Experimental, use at your own risk. This method will be renamed when it becomes stable, this - * will break existing code using it. The internal names of the permitted subclasses of this - * class. May be {@literal null}. - * - * @deprecated this API is experimental. - */ - @Deprecated public List permittedSubclassesExperimental; + /** The internal names of the permitted subclasses of this class. May be {@literal null}. */ + public List permittedSubclasses; /** The record components of this class. May be {@literal null}. */ public List recordComponents; @@ -183,7 +178,7 @@ public class ClassNode extends ClassVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public ClassNode() { - this(Opcodes.ASM8); + this(Opcodes.ASM9); if (getClass() != ClassNode.class) { throw new IllegalStateException(); } @@ -193,8 +188,8 @@ public class ClassNode extends ClassVisitor { * Constructs a new {@link ClassNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8}, or {@link Opcodes#ASM9}. */ public ClassNode(final int api) { super(api); @@ -281,16 +276,9 @@ public class ClassNode extends ClassVisitor { nestMembers = Util.add(nestMembers, nestMember); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { - permittedSubclassesExperimental = Util.add(permittedSubclassesExperimental, permittedSubclass); + public void visitPermittedSubclass(final String permittedSubclass) { + permittedSubclasses = Util.add(permittedSubclasses, permittedSubclass); } @Override @@ -347,11 +335,10 @@ public class ClassNode extends ClassVisitor { * in more recent versions of the ASM API than the given version. * * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5}, - * {@link Opcodes#ASM6}, {@link Opcodes#ASM7}. or {@link Opcodes#ASM8}. + * {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8} or {@link Opcodes#ASM9}. */ - @SuppressWarnings("deprecation") public void check(final int api) { - if (api != Opcodes.ASM9_EXPERIMENTAL && permittedSubclassesExperimental != null) { + if (api < Opcodes.ASM9 && permittedSubclasses != null) { throw new UnsupportedClassVersionException(); } if (api < Opcodes.ASM8 && ((access & Opcodes.ACC_RECORD) != 0 || recordComponents != null)) { @@ -410,7 +397,6 @@ public class ClassNode extends ClassVisitor { * * @param classVisitor a class visitor. */ - @SuppressWarnings("deprecation") public void accept(final ClassVisitor classVisitor) { // Visit the header. String[] interfacesArray = new String[this.interfaces.size()]; @@ -473,10 +459,10 @@ public class ClassNode extends ClassVisitor { classVisitor.visitNestMember(nestMembers.get(i)); } } - // Visit the permitted subclass. - if (permittedSubclassesExperimental != null) { - for (int i = 0, n = permittedSubclassesExperimental.size(); i < n; ++i) { - classVisitor.visitPermittedSubclassExperimental(permittedSubclassesExperimental.get(i)); + // Visit the permitted subclasses. + if (permittedSubclasses != null) { + for (int i = 0, n = permittedSubclasses.size(); i < n; ++i) { + classVisitor.visitPermittedSubclass(permittedSubclasses.get(i)); } } // Visit the inner classes. @@ -500,3 +486,4 @@ public class ClassNode extends ClassVisitor { classVisitor.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java index a340f675c129c189f6bc4ed07001a5a8aada39e3..8dd491246e8cafe3db5d3bd8e3528fe781e74243 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -125,3 +126,4 @@ public class FieldInsnNode extends AbstractInsnNode { return new FieldInsnNode(opcode, owner, name, desc).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java index 93f03da4667657a2b52458507e33d0b7e24597b7..a5034342003d273216ab5982e8b050c58bd0da4f 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -130,7 +131,7 @@ public class FieldNode extends FieldVisitor { final String descriptor, final String signature, final Object value) { - this(/* latest api = */ Opcodes.ASM8, access, name, descriptor, signature, value); + this(/* latest api = */ Opcodes.ASM9, access, name, descriptor, signature, value); if (getClass() != FieldNode.class) { throw new IllegalStateException(); } @@ -140,8 +141,8 @@ public class FieldNode extends FieldVisitor { * Constructs a new {@link FieldNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param access the field's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This parameter * also indicates if the field is synthetic and/or deprecated. * @param name the field's name. @@ -274,3 +275,4 @@ public class FieldNode extends FieldVisitor { fieldVisitor.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java index aa929d00a4053536b6ebf4e5b2446a399f1d4e8c..cd4cc5c57adc0ae4da92e6e8d12ed9ac2298a5b4 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -217,3 +218,4 @@ public class FrameNode extends AbstractInsnNode { return array; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java index a445a27e076ee08132eea0b23e58d0b64283a9e9..c3cdf60337cc428f8619d5ff19fad523b8f0be9a 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -103,3 +104,4 @@ public class IincInsnNode extends AbstractInsnNode { return new IincInsnNode(var, incr).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java index 129bbfa36ff555b570db889b76dda77fd633fc1e..7ab29379ca82288fa5cf839ded056cdeb4ce94df 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import jdk.internal.org.objectweb.asm.ClassVisitor; @@ -114,3 +115,4 @@ public class InnerClassNode { classVisitor.visitInnerClass(name, outerName, innerName, access); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java index 4290c469e2f422285ebd2ac861724632aaeacbd7..a375eb0ce8849b2c79db0d30337da84a1db01d15 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ListIterator; @@ -518,12 +519,19 @@ public class InsnList implements Iterable { AbstractInsnNode remove; InsnListIterator(final int index) { - if (index == size()) { + if (index < 0 || index > size()) { + throw new IndexOutOfBoundsException(); + } else if (index == size()) { nextInsn = null; previousInsn = getLast(); } else { - nextInsn = get(index); - previousInsn = nextInsn.previousInsn; + AbstractInsnNode currentInsn = getFirst(); + for (int i = 0; i < index; i++) { + currentInsn = currentInsn.nextInsn; + } + + nextInsn = currentInsn; + previousInsn = currentInsn.previousInsn; } } @@ -626,3 +634,4 @@ public class InsnList implements Iterable { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java index 6c231722a58454e0ec2661e291b397a23a136376..8fed9db1949e64c59b136b22407a9c8952ec878b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -102,3 +103,4 @@ public class InsnNode extends AbstractInsnNode { return new InsnNode(opcode).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java index 82f885c35a0494815786073eb936775669553494..5da8824ea995b79579a530cf09cd6a40fd7ffb81 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -108,3 +109,4 @@ public class IntInsnNode extends AbstractInsnNode { return new IntInsnNode(opcode, operand).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java index 46878f23b5d535ccf24807fb766ab620b873b813..0d934f2ab73782936ead444e6e7e168d6d7efce1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -121,3 +122,4 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode { return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java index e1f1eb28dd0dfac778ff5403ead98fd3fc033129..8790ff322465a38f660d159d4fce32d29515a276 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -116,3 +117,4 @@ public class JumpInsnNode extends AbstractInsnNode { return new JumpInsnNode(opcode, clone(label, clonedLabels)).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java index 182c54ce10e8c0f9ddfd42461050cbcd494bb0a2..6edcc0d99d10b95e2af3f9176ba77c97488c9e83 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -108,3 +109,4 @@ public class LabelNode extends AbstractInsnNode { value = null; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java index 23309524dcef65df1f109d890024a7d69050aa26..20eafcaa65631d1d499d023d186560cfbe85c4ad 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java @@ -56,11 +56,15 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; +import jdk.internal.org.objectweb.asm.ConstantDynamic; +import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.Type; /** * A node that represents an LDC instruction. @@ -70,17 +74,23 @@ import jdk.internal.org.objectweb.asm.Opcodes; public class LdcInsnNode extends AbstractInsnNode { /** - * The constant to be loaded on the stack. This parameter must be a non null {@link Integer}, a - * {@link Float}, a {@link Long}, a {@link Double}, a {@link String} or a {@link - * jdk.internal.org.objectweb.asm.Type}. + * The constant to be loaded on the stack. This field must be a non null {@link Integer}, a {@link + * Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY + * sort for {@code .class} constants, for classes whose version is 49, a {@link Type} of METHOD + * sort for MethodType, a {@link Handle} for MethodHandle constants, for classes whose version is + * 51 or a {@link ConstantDynamic} for a constant dynamic for classes whose version is 55. */ public Object cst; /** * Constructs a new {@link LdcInsnNode}. * - * @param value the constant to be loaded on the stack. This parameter must be a non null {@link - * Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. + * @param value the constant to be loaded on the stack. This parameter mist be a non null {@link + * Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link + * Type} of OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is + * 49, a {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle + * constants, for classes whose version is 51 or a {@link ConstantDynamic} for a constant + * dynamic for classes whose version is 55. */ public LdcInsnNode(final Object value) { super(Opcodes.LDC); @@ -103,3 +113,4 @@ public class LdcInsnNode extends AbstractInsnNode { return new LdcInsnNode(cst).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java index 92cbac238384169395e779a368ce1b48d409f076..ac882ed778356d50fb4257c7560d24b88b4445e7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -103,3 +104,4 @@ public class LineNumberNode extends AbstractInsnNode { return new LineNumberNode(line, clone(start, clonedLabels)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java index c17e80847c2358dd3ab3cd158ed12f8a43c2144e..54701d78214a23a7bde67fdeb040cf75108d81f0 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -114,15 +115,15 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode { final LabelNode[] end, final int[] index, final String descriptor) { - this(/* latest api = */ Opcodes.ASM8, typeRef, typePath, start, end, index, descriptor); + this(/* latest api = */ Opcodes.ASM9, typeRef, typePath, start, end, index, descriptor); } /** * Constructs a new {@link LocalVariableAnnotationNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}. * @param start the fist instructions corresponding to the continuous ranges that make the scope * of this local variable (inclusive). @@ -169,3 +170,4 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode { typeRef, typePath, startLabels, endLabels, indices, desc, visible)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java index 3a62f0e35c4aa8a3fb172216648715b0a6f9e2c3..142c5915a06cdc343eed0962c9234ebe61113a1e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import jdk.internal.org.objectweb.asm.MethodVisitor; @@ -121,3 +122,4 @@ public class LocalVariableNode { name, desc, signature, start.getLabel(), end.getLabel(), index); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java index 73e0c633a64e781a629072e75c983d8e09e239de..513f2c06cfa6ca338be8b0343b6ee4732e930051 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -122,3 +123,4 @@ public class LookupSwitchInsnNode extends AbstractInsnNode { return clone.cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java index 0b6ff98c89b8eb3b4a4823f0dd7ce7e361de8107..9c5f40d6517bd5d4dc21c2a025863fc3ebc3bbc9 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -152,3 +153,4 @@ public class MethodInsnNode extends AbstractInsnNode { return new MethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java index 7161391b87e1f675d5fd69af46bb996fda04c00b..6af5c517fa9c9e40d186d82a0dc8dd4148462927 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -186,7 +187,7 @@ public class MethodNode extends MethodVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public MethodNode() { - this(/* latest api = */ Opcodes.ASM8); + this(/* latest api = */ Opcodes.ASM9); if (getClass() != MethodNode.class) { throw new IllegalStateException(); } @@ -196,8 +197,8 @@ public class MethodNode extends MethodVisitor { * Constructs an uninitialized {@link MethodNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ public MethodNode(final int api) { super(api); @@ -223,7 +224,7 @@ public class MethodNode extends MethodVisitor { final String descriptor, final String signature, final String[] exceptions) { - this(/* latest api = */ Opcodes.ASM8, access, name, descriptor, signature, exceptions); + this(/* latest api = */ Opcodes.ASM9, access, name, descriptor, signature, exceptions); if (getClass() != MethodNode.class) { throw new IllegalStateException(); } @@ -233,8 +234,8 @@ public class MethodNode extends MethodVisitor { * Constructs a new {@link MethodNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if * the method is synthetic and/or deprecated. * @param name the method's name. @@ -599,7 +600,7 @@ public class MethodNode extends MethodVisitor { * in more recent versions of the ASM API than the given version. * * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5}, - * {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link Opcodes#ASM8}. + * {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8} or {@link Opcodes#ASM9}. */ public void check(final int api) { if (api == Opcodes.ASM4) { @@ -803,3 +804,4 @@ public class MethodNode extends MethodVisitor { methodVisitor.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java index 9d872820da0c9c9885241cac11d7723d4c5995c6..094c2e19300b1ffd86a12035e5e4e98481ffc77c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -108,3 +109,4 @@ public class ModuleExportNode { packaze, access, modules == null ? null : modules.toArray(new String[0])); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java index 8c48d4e8c9c8b22002e80f1332a923d853f6f7b7..fcb9db550f03fbf13c1c4d3f9a038321e0e35d05 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -115,7 +116,7 @@ public class ModuleNode extends ModuleVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public ModuleNode(final String name, final int access, final String version) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); if (getClass() != ModuleNode.class) { throw new IllegalStateException(); } @@ -129,7 +130,7 @@ public class ModuleNode extends ModuleVisitor { * Constructs a {@link ModuleNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link Opcodes#ASM8}. + * Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param name the fully qualified name (using dots) of the module. * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code * ACC_MANDATED}. @@ -264,3 +265,4 @@ public class ModuleNode extends ModuleVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java index baecf6bf4e04578cbf7061e5a799c35381b2a8e1..afc453ef3b10588ca5202587c388416b9bd40add 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -108,3 +109,4 @@ public class ModuleOpenNode { packaze, access, modules == null ? null : modules.toArray(new String[0])); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java index a191a43aa5aee617247173ceda7c6a761105f98a..3370aafe5f2cc3ae58d0c97bbe21318176aa9dc8 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -95,3 +96,4 @@ public class ModuleProvideNode { moduleVisitor.visitProvide(service, providers.toArray(new String[0])); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java index 15ccc4a7bdca65e92ce1615617e7afe35dbfcd60..cec5ebcdbd23cf8a2592564a8190b4cabb1a35fd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import jdk.internal.org.objectweb.asm.ModuleVisitor; @@ -102,3 +103,4 @@ public class ModuleRequireNode { moduleVisitor.visitRequire(module, access, version); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java index fde74ab7f31f3dd55f194cb0663313efd69fe76d..201fb7652d6358afa712ee562848b5f0374c60d5 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -103,3 +104,4 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode { return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java index 30b85c2f49b95f347dcd6a3e9ef8651f60f6b9c5..cb90eb6db5e8b0ec1abbc1c6f1c3002362f64e2e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import jdk.internal.org.objectweb.asm.MethodVisitor; @@ -97,3 +98,4 @@ public class ParameterNode { methodVisitor.visitParameter(name, access); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/RecordComponentNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/RecordComponentNode.java index 0c7f10eeeb9dbdef3709f918342516cff6b107e7..7eb919b7bbb5db75cf4f1aaad54ac6dafd839d14 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/RecordComponentNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/RecordComponentNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -107,7 +108,7 @@ public class RecordComponentNode extends RecordComponentVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public RecordComponentNode(final String name, final String descriptor, final String signature) { - this(/* latest api = */ Opcodes.ASM8, name, descriptor, signature); + this(/* latest api = */ Opcodes.ASM9, name, descriptor, signature); if (getClass() != RecordComponentNode.class) { throw new IllegalStateException(); } @@ -116,7 +117,8 @@ public class RecordComponentNode extends RecordComponentVisitor { /** * Constructs a new {@link RecordComponentNode}. * - * @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM8}. + * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM8} + * or {@link Opcodes#ASM9}. * @param name the record component name. * @param descriptor the record component descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). * @param signature the record component signature. @@ -175,7 +177,7 @@ public class RecordComponentNode extends RecordComponentVisitor { * method checks that this node, and all its children recursively, do not contain elements that * were introduced in more recent versions of the ASM API than the given version. * - * @param api an ASM API version. Must be {@link Opcodes#ASM8}. + * @param api an ASM API version. Must be one of {@link Opcodes#ASM8} or {@link Opcodes#ASM9}. */ public void check(final int api) { if (api < Opcodes.ASM8) { @@ -232,3 +234,4 @@ public class RecordComponentNode extends RecordComponentVisitor { recordComponentVisitor.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java index 1dbf92548a4bedaf154cc3ad07b47677a726b6e2..cabc1553c695d10c07e45da107a9447cf688a217 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -122,3 +123,4 @@ public class TableSwitchInsnNode extends AbstractInsnNode { .cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java index e172cde4cc6bfe2b88a09989af885d5c534ff28b..fe033a5bc7c273306aaed6b139a98a2d40b801e8 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.List; @@ -155,3 +156,4 @@ public class TryCatchBlockNode { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java index 83b34af13184a8a94f519dbb6f7776c81a5f594b..023882bca2d751127228ab01d86db2933cf6c1fd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import jdk.internal.org.objectweb.asm.Opcodes; @@ -90,7 +91,7 @@ public class TypeAnnotationNode extends AnnotationNode { * @throws IllegalStateException If a subclass calls this constructor. */ public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String descriptor) { - this(/* latest api = */ Opcodes.ASM8, typeRef, typePath, descriptor); + this(/* latest api = */ Opcodes.ASM9, typeRef, typePath, descriptor); if (getClass() != TypeAnnotationNode.class) { throw new IllegalStateException(); } @@ -100,8 +101,8 @@ public class TypeAnnotationNode extends AnnotationNode { * Constructs a new {@link AnnotationNode}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}. * @param typePath the path to the annotated type argument, wildcard bound, array element type, or * static inner type within 'typeRef'. May be {@literal null} if the annotation targets @@ -115,3 +116,4 @@ public class TypeAnnotationNode extends AnnotationNode { this.typePath = typePath; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java index 1bc6f3275a3d70e45ad4c4a904c808cd642a9249..3ebdfab6ceedb00d6ec0e83fd48b56aee36ddaeb 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -114,3 +115,4 @@ public class TypeInsnNode extends AbstractInsnNode { return new TypeInsnNode(opcode, desc).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java index 8eb50e4c055dd7064efa403782200104e9c00b21..17f9ebb2e35c739186e5a8ca26ae48a33ae5a065 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java @@ -55,7 +55,8 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. - */package jdk.internal.org.objectweb.asm.tree; + */ +package jdk.internal.org.objectweb.asm.tree; /** * Exception thrown in {@link AnnotationNode#check}, {@link ClassNode#check}, {@link @@ -69,3 +70,4 @@ public class UnsupportedClassVersionException extends RuntimeException { private static final long serialVersionUID = -3502347765891805831L; } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/Util.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/Util.java index 38e30fa1340da0a88c3003c43a8c294989022898..eeb7261bb9a4810d259b36444c72815c35c4052d 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/Util.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/Util.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.ArrayList; @@ -192,3 +193,4 @@ final class Util { return list; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java index 7c41463b09bc7911b9b7b2e018f7d4cb51ee9d1d..df6d834a6c0967ab6308037e888fa45872a1a77c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree; import java.util.Map; @@ -111,3 +112,4 @@ public class VarInsnNode extends AbstractInsnNode { return new VarInsnNode(opcode, var).cloneAnnotations(this); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java index 31b879291f3f39f95b7460c93abdff4c33bd6cbf..8c5e315ff0921b11f39886e83c69121e1760b746 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.ArrayList; @@ -124,7 +125,8 @@ public class Analyzer implements Opcodes { * Analyzes the given method. * * @param owner the internal name of the class to which 'method' belongs. - * @param method the method to be analyzed. + * @param method the method to be analyzed. The maxStack and maxLocals fields must have correct + * values. * @return the symbolic state of the execution stack frame at each bytecode instruction of the * method. The size of the returned array is equal to the number of instructions (and labels) * of the method. A given frame is {@literal null} if and only if the corresponding @@ -330,6 +332,74 @@ public class Analyzer implements Opcodes { return frames; } + /** + * Analyzes the given method and computes and sets its maximum stack size and maximum number of + * local variables. + * + * @param owner the internal name of the class to which 'method' belongs. + * @param method the method to be analyzed. + * @return the symbolic state of the execution stack frame at each bytecode instruction of the + * method. The size of the returned array is equal to the number of instructions (and labels) + * of the method. A given frame is {@literal null} if and only if the corresponding + * instruction cannot be reached (dead code). + * @throws AnalyzerException if a problem occurs during the analysis. + */ + public Frame[] analyzeAndComputeMaxs(final String owner, final MethodNode method) + throws AnalyzerException { + method.maxLocals = computeMaxLocals(method); + method.maxStack = -1; + analyze(owner, method); + method.maxStack = computeMaxStack(frames); + return frames; + } + + /** + * Computes and returns the maximum number of local variables used in the given method. + * + * @param method a method. + * @return the maximum number of local variables used in the given method. + */ + private static int computeMaxLocals(final MethodNode method) { + int maxLocals = Type.getArgumentsAndReturnSizes(method.desc) >> 2; + for (AbstractInsnNode insnNode : method.instructions) { + if (insnNode instanceof VarInsnNode) { + int local = ((VarInsnNode) insnNode).var; + int size = + (insnNode.getOpcode() == Opcodes.LLOAD + || insnNode.getOpcode() == Opcodes.DLOAD + || insnNode.getOpcode() == Opcodes.LSTORE + || insnNode.getOpcode() == Opcodes.DSTORE) + ? 2 + : 1; + maxLocals = Math.max(maxLocals, local + size); + } else if (insnNode instanceof IincInsnNode) { + int local = ((IincInsnNode) insnNode).var; + maxLocals = Math.max(maxLocals, local + 1); + } + } + return maxLocals; + } + + /** + * Computes and returns the maximum stack size of a method, given its stack map frames. + * + * @param frames the stack map frames of a method. + * @return the maximum stack size of the given method. + */ + private static int computeMaxStack(final Frame[] frames) { + int maxStack = 0; + for (Frame frame : frames) { + if (frame != null) { + int stackSize = 0; + for (int i = 0; i < frame.getStackSize(); ++i) { + stackSize += frame.getStack(i).getSize(); + } + maxStack = Math.max(maxStack, stackSize); + } + } + return maxStack; + } + /** * Follows the control flow graph of the currently analyzed method, starting at the given * instruction index, and stores a copy of the given subroutine in {@link #subroutines} for each @@ -632,3 +702,4 @@ public class Analyzer implements Opcodes { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java index c74f873a80c66c40c55c64c830bb93183f67f127..e3ea04720bed08f77a5c3f9ac5a33200c19db310 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; @@ -118,3 +119,4 @@ public class AnalyzerException extends Exception { this.node = insn; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java index 0b7997e5092fcf3f9ea2e7f6d8403305ecf1ba86..d640e0a06f8aae9fc2b5e5e0d51ba130bd99251a 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.List; @@ -92,7 +93,7 @@ public class BasicInterpreter extends Interpreter implements Opcodes * version. */ public BasicInterpreter() { - super(/* latest api = */ ASM8); + super(/* latest api = */ ASM9); if (getClass() != BasicInterpreter.class) { throw new IllegalStateException(); } @@ -103,8 +104,8 @@ public class BasicInterpreter extends Interpreter implements Opcodes * * @param api the ASM API version supported by this interpreter. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. */ protected BasicInterpreter(final int api) { super(api); @@ -406,3 +407,4 @@ public class BasicInterpreter extends Interpreter implements Opcodes return value1; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java index fea4e140d0f0d0cffc34b338bb48281526b28c67..58b57120ebd5cb4813feee6dfac251957bef1e9f 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import jdk.internal.org.objectweb.asm.Type; @@ -158,3 +159,4 @@ public class BasicValue implements Value { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java index dd89834c3c5fb3b43767c60d69f37643921ea637..7a3b6b8ab634e63127bec40975cf94257b78123b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.List; @@ -78,7 +79,7 @@ public class BasicVerifier extends BasicInterpreter { * use this constructor. Instead, they must use the {@link #BasicVerifier(int)} version. */ public BasicVerifier() { - super(/* latest api = */ ASM8); + super(/* latest api = */ ASM9); if (getClass() != BasicVerifier.class) { throw new IllegalStateException(); } @@ -89,8 +90,8 @@ public class BasicVerifier extends BasicInterpreter { * * @param api the ASM API version supported by this interpreter. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. */ protected BasicVerifier(final int api) { super(api); @@ -480,3 +481,4 @@ public class BasicVerifier extends BasicInterpreter { return value.equals(expected); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java index 1e57017c7046de2fe966ecc234b5135fc1ae64ec..ddb477d6f7b4819621f6a6ee973890f84e2918df 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.ArrayList; @@ -80,6 +81,9 @@ import jdk.internal.org.objectweb.asm.tree.VarInsnNode; */ public class Frame { + /** The maximum size of the operand stack of any method. */ + private static final int MAX_STACK_SIZE = 65536; + /** * The expected return type of the analyzed method, or {@literal null} if the method returns void. */ @@ -88,26 +92,43 @@ public class Frame { /** * The local variables and the operand stack of this frame. The first {@link #numLocals} elements * correspond to the local variables. The following {@link #numStack} elements correspond to the - * operand stack. + * operand stack. Long and double values are represented with two elements in the local variables + * section, and with one element in the operand stack section. */ private V[] values; - /** The number of local variables of this frame. */ + /** + * The number of local variables of this frame. Long and double values are represented with two + * elements. + */ private int numLocals; - /** The number of elements in the operand stack. */ + /** + * The number of elements in the operand stack. Long and double values are represented with a + * single element. + */ private int numStack; + /** + * The maximum number of elements in the operand stack. Long and double values are represented + * with a single element. + */ + private int maxStack; + /** * Constructs a new frame with the given size. * - * @param numLocals the maximum number of local variables of the frame. - * @param numStack the maximum stack size of the frame. + * @param numLocals the number of local variables of the frame. Long and double values are + * represented with two elements. + * @param maxStack the maximum number of elements in the operand stack, or -1 if there is no + * maximum value. Long and double values are represented with a single element. */ @SuppressWarnings("unchecked") - public Frame(final int numLocals, final int numStack) { - this.values = (V[]) new Value[numLocals + numStack]; + public Frame(final int numLocals, final int maxStack) { + this.values = (V[]) new Value[numLocals + (maxStack >= 0 ? maxStack : 4)]; this.numLocals = numLocals; + this.numStack = 0; + this.maxStack = maxStack >= 0 ? maxStack : MAX_STACK_SIZE; } /** @@ -128,8 +149,14 @@ public class Frame { */ public Frame init(final Frame frame) { returnValue = frame.returnValue; - System.arraycopy(frame.values, 0, values, 0, values.length); + if (values.length < frame.values.length) { + values = frame.values.clone(); + } else { + System.arraycopy(frame.values, 0, values, 0, frame.values.length); + } + numLocals = frame.numLocals; numStack = frame.numStack; + maxStack = frame.maxStack; return this; } @@ -166,7 +193,8 @@ public class Frame { } /** - * Returns the maximum number of local variables of this frame. + * Returns the maximum number of local variables of this frame. Long and double values are + * represented with two variables. * * @return the maximum number of local variables of this frame. */ @@ -175,16 +203,18 @@ public class Frame { } /** - * Returns the maximum stack size of this frame. + * Returns the maximum number of elements in the operand stack of this frame. Long and double + * values are represented with a single element. * - * @return the maximum stack size of this frame. + * @return the maximum number of elements in the operand stack of this frame. */ public int getMaxStackSize() { - return values.length - numLocals; + return maxStack; } /** - * Returns the value of the given local variable. + * Returns the value of the given local variable. Long and double values are represented with two + * variables. * * @param index a local variable index. * @return the value of the given local variable. @@ -198,7 +228,8 @@ public class Frame { } /** - * Sets the value of the given local variable. + * Sets the value of the given local variable. Long and double values are represented with two + * variables. * * @param index a local variable index. * @param value the new value of this local variable. @@ -212,10 +243,10 @@ public class Frame { } /** - * Returns the number of values in the operand stack of this frame. Long and double values are - * treated as single values. + * Returns the number of elements in the operand stack of this frame. Long and double values are + * represented with a single element. * - * @return the number of values in the operand stack of this frame. + * @return the number of elements in the operand stack of this frame. */ public int getStackSize() { return numStack; @@ -267,9 +298,15 @@ public class Frame { * @param value the value that must be pushed into the stack. * @throws IndexOutOfBoundsException if the operand stack is full. */ + @SuppressWarnings("unchecked") public void push(final V value) { if (numLocals + numStack >= values.length) { - throw new IndexOutOfBoundsException("Insufficient maximum stack size."); + if (numLocals + numStack >= maxStack) { + throw new IndexOutOfBoundsException("Insufficient maximum stack size."); + } + V[] oldValues = values; + values = (V[]) new Value[2 * values.length]; + System.arraycopy(oldValues, 0, values, 0, oldValues.length); } values[numLocals + (numStack++)] = value; } @@ -745,3 +782,4 @@ public class Frame { return stringBuilder.toString(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java index d9b722e098e67759f16b017b12200decd5938b4e..ed8deff40224b121b25e911c63d287bc6d8e52a9 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.List; @@ -297,3 +298,4 @@ public abstract class Interpreter { */ public abstract V merge(V value1, V value2); } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java index 0e14dcc986419655d5c829d0108c7580140fe9dc..cb426dea3988a0f6fa9fb98bdfd766947dc6742d 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.List; @@ -125,7 +126,7 @@ public class SimpleVerifier extends BasicVerifier { final List currentClassInterfaces, final boolean isInterface) { this( - /* latest api = */ ASM8, + /* latest api = */ ASM9, currentClass, currentSuperClass, currentClassInterfaces, @@ -141,8 +142,8 @@ public class SimpleVerifier extends BasicVerifier { * * @param api the ASM API version supported by this verifier. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. * @param currentClass the type of the class to be verified. * @param currentSuperClass the type of the super class of the class to be verified. * @param currentClassInterfaces the types of the interfaces directly implemented by the class to @@ -411,3 +412,4 @@ public class SimpleVerifier extends BasicVerifier { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java index 6f8ad5621bcb870cde19d73c661f3146ded4bff7..099a73779444c1ec9574810e1ba9098fbde07429 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.AbstractSet; @@ -227,3 +228,4 @@ final class SmallSet extends AbstractSet { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java index 786aed688ca38fa157fad865bbd9f438a7833a64..bb242af2ff53ef75281bcbb6aa2c41db71026ad1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.HashSet; @@ -82,7 +83,7 @@ public class SourceInterpreter extends Interpreter implements Opcod * version. */ public SourceInterpreter() { - super(/* latest api = */ ASM8); + super(/* latest api = */ ASM9); if (getClass() != SourceInterpreter.class) { throw new IllegalStateException(); } @@ -93,8 +94,8 @@ public class SourceInterpreter extends Interpreter implements Opcod * * @param api the ASM API version supported by this interpreter. Must be one of {@link * jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7} or {@link - * jdk.internal.org.objectweb.asm.Opcodes#ASM8}. + * jdk.internal.org.objectweb.asm.Opcodes#ASM6}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}, {@link + * jdk.internal.org.objectweb.asm.Opcodes#ASM8} or or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM9}. */ protected SourceInterpreter(final int api) { super(api); @@ -251,3 +252,4 @@ public class SourceInterpreter extends Interpreter implements Opcod return self.containsAll(other); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java index eb0f619b913d5218f97e71bc8ce379d863f5dcf3..926c2c2831426c21ae78706f5464890fdb8c6311 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.Set; @@ -148,3 +149,4 @@ public class SourceValue implements Value { return insns.hashCode(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java index 1b38879edb15242bde5e122bd0e32da9268d1c11..f59644795d715ccc707048789675384dd2d88699 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; import java.util.ArrayList; @@ -135,3 +136,4 @@ final class Subroutine { return changed; } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java index 5c8f0c97c17bc3cf5969405f693e57e22cdfe328..450120c741a80bec53e6678faba0f648038179fa 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.tree.analysis; /** @@ -73,3 +74,4 @@ public interface Value { */ int getSize(); } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java deleted file mode 100644 index 541f145a0f593d42c1e59d1643c715497fb64aa2..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package jdk.internal.org.objectweb.asm.util; - -import java.util.Map; -import jdk.internal.org.objectweb.asm.Label; - -/** - * An {@link jdk.internal.org.objectweb.asm.Attribute} that can generate the ASM code to create an equivalent - * attribute. - * - * @author Eugene Kuleshov - */ -// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). -public interface ASMifiable { - - /** - * Generates the ASM code to create an attribute equal to this attribute. - * - * @param outputBuffer where the generated code must be appended. - * @param visitorVariableName the name of the visitor variable in the produced code. - * @param labelNames the names of the labels in the generated code. - */ - void asmify(StringBuffer outputBuffer, String visitorVariableName, Map labelNames); -} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java index b6d0267e74847beaae8274838471f00e00dbdd76..3db7eba438beb53dd486ccd144a8d1199f963a63 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.IOException; @@ -84,7 +85,7 @@ public class ASMifier extends Printer { /** The help message shown when command line arguments are incorrect. */ private static final String USAGE = "Prints the ASM code to generate the given class.\n" - + "Usage: ASMifier [-debug] "; + + "Usage: ASMifier [-nodebug] "; /** A pseudo access flag used to distinguish class access flags. */ private static final int ACCESS_CLASS = 0x40000; @@ -136,6 +137,9 @@ public class ASMifier extends Printer { classVersions.put(Opcodes.V13, "V13"); classVersions.put(Opcodes.V14, "V14"); classVersions.put(Opcodes.V15, "V15"); + classVersions.put(Opcodes.V16, "V16"); + classVersions.put(Opcodes.V17, "V17"); + classVersions.put(Opcodes.V18, "V18"); CLASS_VERSIONS = Collections.unmodifiableMap(classVersions); } @@ -155,7 +159,7 @@ public class ASMifier extends Printer { * @throws IllegalStateException If a subclass calls this constructor. */ public ASMifier() { - this(/* latest api = */ Opcodes.ASM8, "classWriter", 0); + this(/* latest api = */ Opcodes.ASM9, "classWriter", 0); if (getClass() != ASMifier.class) { throw new IllegalStateException(); } @@ -165,7 +169,8 @@ public class ASMifier extends Printer { * Constructs a new {@link ASMifier}. * * @param api the ASM API version implemented by this class. Must be one of {@link Opcodes#ASM4}, - * {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link Opcodes#ASM8}. + * {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link Opcodes#ASM8} or + * {@link Opcodes#ASM9}. * @param visitorVariableName the name of the visitor variable in the produced code. * @param annotationVisitorId identifier of the annotation visitor variable in the produced code. */ @@ -179,7 +184,7 @@ public class ASMifier extends Printer { /** * Prints the ASM source code to generate the given class to the standard output. * - *

    Usage: ASMifier [-debug] <binary class name or class file name> + *

    Usage: ASMifier [-nodebug] <binary class name or class file name> * * @param args the command line arguments. * @throws IOException if the class cannot be found, or if an IOException occurs. @@ -191,7 +196,7 @@ public class ASMifier extends Printer { /** * Prints the ASM source code to generate the given class to the given output. * - *

    Usage: ASMifier [-debug] <binary class name or class file name> + *

    Usage: ASMifier [-nodebug] <binary class name or class file name> * * @param args the command line arguments. * @param output where to print the result. @@ -354,17 +359,10 @@ public class ASMifier extends Printer { text.add(stringBuilder.toString()); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { + public void visitPermittedSubclass(final String permittedSubclass) { stringBuilder.setLength(0); - stringBuilder.append("classWriter.visitPermittedSubclassExperimental("); + stringBuilder.append("classWriter.visitPermittedSubclass("); appendConstant(permittedSubclass); stringBuilder.append(END_PARAMETERS); text.add(stringBuilder.toString()); @@ -664,9 +662,7 @@ public class ASMifier extends Printer { @Override public void visitRecordComponentEnd() { - stringBuilder.setLength(0); - stringBuilder.append(name).append(VISIT_END); - text.add(stringBuilder.toString()); + visitMemberEnd(); } // ----------------------------------------------------------------------------------------------- @@ -691,9 +687,7 @@ public class ASMifier extends Printer { @Override public void visitFieldEnd() { - stringBuilder.setLength(0); - stringBuilder.append(name).append(VISIT_END); - text.add(stringBuilder.toString()); + visitMemberEnd(); } // ----------------------------------------------------------------------------------------------- @@ -1166,9 +1160,7 @@ public class ASMifier extends Printer { @Override public void visitMethodEnd() { - stringBuilder.setLength(0); - stringBuilder.append(name).append(VISIT_END); - text.add(stringBuilder.toString()); + visitMemberEnd(); } // ----------------------------------------------------------------------------------------------- @@ -1278,6 +1270,13 @@ public class ASMifier extends Printer { text.add(stringBuilder.toString()); } + /** Visits the end of a field, record component or method. */ + private void visitMemberEnd() { + stringBuilder.setLength(0); + stringBuilder.append(name).append(VISIT_END); + text.add(stringBuilder.toString()); + } + // ----------------------------------------------------------------------------------------------- // Utility methods // ----------------------------------------------------------------------------------------------- @@ -1645,3 +1644,4 @@ public class ASMifier extends Printer { stringBuilder.append(labelNames.get(label)); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifierSupport.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifierSupport.java index b399fb27d5833a58a967c933598456804936e3ae..956938394a4d7e575cee4d6cebd6c534d3624d33 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifierSupport.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifierSupport.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.util.Map; @@ -80,3 +81,4 @@ public interface ASMifierSupport { void asmify( StringBuilder outputBuilder, String visitorVariableName, Map labelNames); } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java index 07634756103b3c698ff39817ad51420b621b55d1..b3d21f5ae997d56fb87340c2c0f05854a0b9e94b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -83,7 +84,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } CheckAnnotationAdapter(final AnnotationVisitor annotationVisitor, final boolean useNamedValues) { - super(/* latest api = */ Opcodes.ASM8, annotationVisitor); + super(/* latest api = */ Opcodes.ASM9, annotationVisitor); this.useNamedValue = useNamedValues; } @@ -164,3 +165,4 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java index 4de5d38ae4ead3978466701de38a1198a369988c..a25280570077866adc4bba4c4cb53cce4bfb2a0a 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.FileInputStream; @@ -205,7 +206,7 @@ public class CheckClassAdapter extends ClassVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public CheckClassAdapter(final ClassVisitor classVisitor, final boolean checkDataFlow) { - this(/* latest api = */ Opcodes.ASM8, classVisitor, checkDataFlow); + this(/* latest api = */ Opcodes.ASM9, classVisitor, checkDataFlow); if (getClass() != CheckClassAdapter.class) { throw new IllegalStateException(); } @@ -215,8 +216,8 @@ public class CheckClassAdapter extends ClassVisitor { * Constructs a new {@link CheckClassAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param classVisitor the class visitor to which this adapter must delegate calls. * @param checkDataFlow {@literal true} to perform basic data flow checks, or {@literal false} to * not perform any data flow check (see {@link CheckMethodAdapter}). This option requires @@ -353,18 +354,11 @@ public class CheckClassAdapter extends ClassVisitor { super.visitNestMember(nestMember); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { + public void visitPermittedSubclass(final String permittedSubclass) { checkState(); CheckMethodAdapter.checkInternalName(version, permittedSubclass, "permittedSubclass"); - super.visitPermittedSubclassExperimental(permittedSubclass); + super.visitPermittedSubclass(permittedSubclass); } @Override @@ -468,7 +462,8 @@ public class CheckClassAdapter extends ClassVisitor { final String signature, final String[] exceptions) { checkState(); - checkAccess( + checkMethodAccess( + version, access, Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE @@ -593,6 +588,23 @@ public class CheckClassAdapter extends ClassVisitor { } } + /** + * Checks that the given access flags do not contain invalid flags for a method. This method also + * checks that mutually incompatible flags are not set simultaneously. + * + * @param version the class version. + * @param access the method access flags to be checked. + * @param possibleAccess the valid access flags. + */ + private static void checkMethodAccess( + final int version, final int access, final int possibleAccess) { + checkAccess(access, possibleAccess); + if ((version & 0xFFFF) < Opcodes.V17 + && Integer.bitCount(access & (Opcodes.ACC_STRICT | Opcodes.ACC_ABSTRACT)) > 1) { + throw new IllegalArgumentException("strictfp and abstract are mutually exclusive: " + access); + } + } + /** * Checks that the given name is a fully qualified name, using dots. * @@ -981,9 +993,9 @@ public class CheckClassAdapter extends ClassVisitor { mask = 0xFF0000FF; break; default: - throw new AssertionError(); + break; } - if ((typeRef & ~mask) != 0) { + if (mask == 0 || (typeRef & ~mask) != 0) { throw new IllegalArgumentException( "Invalid type reference 0x" + Integer.toHexString(typeRef)); } @@ -1034,9 +1046,10 @@ public class CheckClassAdapter extends ClassVisitor { ClassReader classReader; if (args[0].endsWith(".class")) { - InputStream inputStream = - new FileInputStream(args[0]); // NOPMD(AvoidFileStream): can't fix for 1.5 compatibility - classReader = new ClassReader(inputStream); + // Can't fix PMD warning for 1.5 compatibility. + try (InputStream inputStream = new FileInputStream(args[0])) { // NOPMD(AvoidFileStream) + classReader = new ClassReader(inputStream); + } } else { classReader = new ClassReader(args[0]); } @@ -1065,7 +1078,6 @@ public class CheckClassAdapter extends ClassVisitor { * @param printResults whether to print the results of the bytecode verification. * @param printWriter where the results (or the stack trace in case of error) must be printed. */ - @SuppressWarnings("deprecation") public static void verify( final ClassReader classReader, final ClassLoader loader, @@ -1073,7 +1085,7 @@ public class CheckClassAdapter extends ClassVisitor { final PrintWriter printWriter) { ClassNode classNode = new ClassNode(); classReader.accept( - new CheckClassAdapter(Opcodes.ASM9_EXPERIMENTAL, classNode, false) {}, + new CheckClassAdapter(/*latest*/ Opcodes.ASM9, classNode, false) {}, ClassReader.SKIP_DEBUG); Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName); @@ -1152,7 +1164,12 @@ public class CheckClassAdapter extends ClassVisitor { if (name.charAt(endIndex - 1) == ';') { endIndex--; } - return name.substring(lastSlashIndex + 1, endIndex); + int lastBracketIndex = name.lastIndexOf('['); + if (lastBracketIndex == -1) { + return name.substring(lastSlashIndex + 1, endIndex); + } + return name.substring(0, lastBracketIndex + 1) + name.substring(lastSlashIndex + 1, endIndex); } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java index 8ac6fea420edc9a88ea6aaa3674bf16f4c1d7a05..edb38aca7b13742417f75d6731b3fbdef35c4199 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -83,7 +84,7 @@ public class CheckFieldAdapter extends FieldVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public CheckFieldAdapter(final FieldVisitor fieldVisitor) { - this(/* latest api = */ Opcodes.ASM8, fieldVisitor); + this(/* latest api = */ Opcodes.ASM9, fieldVisitor); if (getClass() != CheckFieldAdapter.class) { throw new IllegalStateException(); } @@ -93,8 +94,8 @@ public class CheckFieldAdapter extends FieldVisitor { * Constructs a new {@link CheckFieldAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param fieldVisitor the field visitor to which this adapter must delegate calls. */ protected CheckFieldAdapter(final int api, final FieldVisitor fieldVisitor) { @@ -146,3 +147,4 @@ public class CheckFieldAdapter extends FieldVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java index 6ecf4604368ca18bbbe4d912a589044b7f152759..7f3816788da5afa67032ef8ea46df38641957122 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.PrintWriter; @@ -398,7 +399,7 @@ public class CheckMethodAdapter extends MethodVisitor { */ public CheckMethodAdapter( final MethodVisitor methodVisitor, final Map labelInsnIndices) { - this(/* latest api = */ Opcodes.ASM8, methodVisitor, labelInsnIndices); + this(/* latest api = */ Opcodes.ASM9, methodVisitor, labelInsnIndices); if (getClass() != CheckMethodAdapter.class) { throw new IllegalStateException(); } @@ -409,8 +410,8 @@ public class CheckMethodAdapter extends MethodVisitor { * data flow check (see {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). * * @param api the ASM API version implemented by this CheckMethodAdapter. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param methodVisitor the method visitor to which this adapter must delegate calls. * @param labelInsnIndices the index of the instruction designated by each visited label so far * (in other methods). This map is updated with the labels from the visited method. @@ -446,7 +447,7 @@ public class CheckMethodAdapter extends MethodVisitor { final MethodVisitor methodVisitor, final Map labelInsnIndices) { this( - /* latest api = */ Opcodes.ASM8, access, name, descriptor, methodVisitor, labelInsnIndices); + /* latest api = */ Opcodes.ASM9, access, name, descriptor, methodVisitor, labelInsnIndices); if (getClass() != CheckMethodAdapter.class) { throw new IllegalStateException(); } @@ -458,8 +459,8 @@ public class CheckMethodAdapter extends MethodVisitor { * instruction IRETURN, or the invalid sequence IADD L2I will be detected. * * @param api the ASM API version implemented by this CheckMethodAdapter. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param access the method's access flags. * @param name the method's name. * @param descriptor the method's descriptor (see {@link Type}). @@ -515,7 +516,7 @@ public class CheckMethodAdapter extends MethodVisitor { checkUnqualifiedName(version, name, "name"); } CheckClassAdapter.checkAccess( - access, Opcodes.ACC_FINAL + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC); + access, Opcodes.ACC_FINAL | Opcodes.ACC_MANDATED | Opcodes.ACC_SYNTHETIC); super.visitParameter(name, access); } @@ -815,7 +816,7 @@ public class CheckMethodAdapter extends MethodVisitor { checkVisitMaxsNotCalled(); checkLabel(label, false, "label"); if (labelInsnIndices.get(label) != null) { - throw new IllegalArgumentException("Already visited label"); + throw new IllegalStateException("Already visited label"); } labelInsnIndices.put(label, insnCount); super.visitLabel(label); @@ -1473,3 +1474,4 @@ public class CheckMethodAdapter extends MethodVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java index 1eae61ba66fb3aa8b07b261de9c150cde9ce7d66..91e85ce2a5b91aeda7ba75ccc05130c1af5d1d81 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.util.HashSet; @@ -102,7 +103,7 @@ public class CheckModuleAdapter extends ModuleVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public CheckModuleAdapter(final ModuleVisitor moduleVisitor, final boolean isOpen) { - this(/* latest api = */ Opcodes.ASM8, moduleVisitor, isOpen); + this(/* latest api = */ Opcodes.ASM9, moduleVisitor, isOpen); if (getClass() != CheckModuleAdapter.class) { throw new IllegalStateException(); } @@ -112,8 +113,8 @@ public class CheckModuleAdapter extends ModuleVisitor { * Constructs a new {@link CheckModuleAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param moduleVisitor the module visitor to which this adapter must delegate calls. * @param isOpen whether the visited module is open. Open modules have their {@link * Opcodes#ACC_OPEN} access flag set in {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitModule}. @@ -242,3 +243,4 @@ public class CheckModuleAdapter extends ModuleVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckRecordComponentAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckRecordComponentAdapter.java index 2c2f976510187ef8119d662823861331e4f18241..98cbb9c4e42f45769486005a90a07e5300417acd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckRecordComponentAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckRecordComponentAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -86,7 +87,7 @@ public class CheckRecordComponentAdapter extends RecordComponentVisitor { * @throws IllegalStateException If a subclass calls this constructor. */ public CheckRecordComponentAdapter(final RecordComponentVisitor recordComponentVisitor) { - this(/* latest api =*/ Opcodes.ASM8, recordComponentVisitor); + this(/* latest api =*/ Opcodes.ASM9, recordComponentVisitor); if (getClass() != CheckRecordComponentAdapter.class) { throw new IllegalStateException(); } @@ -95,7 +96,8 @@ public class CheckRecordComponentAdapter extends RecordComponentVisitor { /** * Constructs a new {@link CheckRecordComponentAdapter}. * - * @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM8}. + * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM8} + * or {@link Opcodes#ASM9}. * @param recordComponentVisitor the record component visitor to which this adapter must delegate * calls. */ @@ -149,3 +151,4 @@ public class CheckRecordComponentAdapter extends RecordComponentVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java index f05054afcb76f30c348da0010fba52a516e46cba..d16f45a8eca6222e288d469ef3b91cb39b17ac63 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.util.EnumSet; @@ -154,15 +155,15 @@ public class CheckSignatureAdapter extends SignatureVisitor { * null}. */ public CheckSignatureAdapter(final int type, final SignatureVisitor signatureVisitor) { - this(/* latest api = */ Opcodes.ASM8, type, signatureVisitor); + this(/* latest api = */ Opcodes.ASM9, type, signatureVisitor); } /** * Constructs a new {@link CheckSignatureAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}. * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal @@ -389,3 +390,4 @@ public class CheckSignatureAdapter extends SignatureVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java index 0c8a0e8f56e71cf11e1109585179f862db778805..19e7bc4cd66050d1697a0c79342663ca2e02bf82 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.FileInputStream; @@ -323,7 +324,8 @@ public abstract class Printer { /** * The ASM API version implemented by this class. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ protected final int api; @@ -485,18 +487,12 @@ public abstract class Printer { } /** - * Experimental, use at your own risk. This method will be renamed when it becomes stable, this - * will break existing code using it. - * - *

    Visits a permitted subclass. A permitted subtclass is one of the allowed subclasses of the - * current class. See {@link - * jdk.internal.org.objectweb.asm.ClassVisitor#visitPermittedSubclassExperimental(String)}. + * Visits a permitted subclasses. A permitted subclass is one of the allowed subclasses of the + * current class. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitPermittedSubclass(String)}. * * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. */ - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { + public void visitPermittedSubclass(final String permittedSubclass) { throw new UnsupportedOperationException(UNSUPPORTED_OPERATION); } @@ -1305,7 +1301,7 @@ public abstract class Printer { /** * Prints a the given class to the given output. * - *

    Command line arguments: [-debug] <binary class name or class file name > + *

    Command line arguments: [-nodebug] <binary class name or class file name > * * @param args the command line arguments. * @param usage the help message to show when command line arguments are incorrect. @@ -1321,7 +1317,9 @@ public abstract class Printer { final PrintWriter output, final PrintWriter logger) throws IOException { - if (args.length < 1 || args.length > 2 || (args[0].equals("-debug") && args.length != 2)) { + if (args.length < 1 + || args.length > 2 + || ((args[0].equals("-debug") || args[0].equals("-nodebug")) && args.length != 2)) { logger.println(usage); return; } @@ -1330,7 +1328,7 @@ public abstract class Printer { String className; int parsingOptions; - if (args[0].equals("-debug")) { + if (args[0].equals("-nodebug")) { className = args[1]; parsingOptions = ClassReader.SKIP_DEBUG; } else { @@ -1341,11 +1339,13 @@ public abstract class Printer { if (className.endsWith(".class") || className.indexOf('\\') != -1 || className.indexOf('/') != -1) { - InputStream inputStream = - new FileInputStream(className); // NOPMD(AvoidFileStream): can't fix for 1.5 compatibility - new ClassReader(inputStream).accept(traceClassVisitor, parsingOptions); + // Can't fix PMD warning for 1.5 compatibility. + try (InputStream inputStream = new FileInputStream(className)) { // NOPMD(AvoidFileStream) + new ClassReader(inputStream).accept(traceClassVisitor, parsingOptions); + } } else { new ClassReader(className).accept(traceClassVisitor, parsingOptions); } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java deleted file mode 100644 index 78ed7e100333733319370e1b1a9b2b393a055e83..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package jdk.internal.org.objectweb.asm.util; - -import java.util.Map; -import jdk.internal.org.objectweb.asm.Label; - -/** - * An {@link jdk.internal.org.objectweb.asm.Attribute} that can print a readable representation of itself. - * - * @author Eugene Kuleshov - */ -public interface Textifiable { - - /** - * Generates a human readable representation of this attribute. - * - * @param outputBuffer where the human representation of this attribute must be appended. - * @param labelNames the human readable names of the labels. - */ - void textify(StringBuffer outputBuffer, Map labelNames); -} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java index ace4f792545b0f13f4504333a268993ac964a904..63074314bc858a9972ac219db15c8f9d035f4a87 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.IOException; @@ -84,7 +85,7 @@ public class Textifier extends Printer { /** The help message shown when command line arguments are incorrect. */ private static final String USAGE = "Prints a disassembled view of the given class.\n" - + "Usage: Textifier [-debug] "; + + "Usage: Textifier [-nodebug] "; /** The type of internal names. See {@link #appendDescriptor}. */ public static final int INTERNAL_NAME = 0; @@ -143,7 +144,7 @@ public class Textifier extends Printer { * @throws IllegalStateException If a subclass calls this constructor. */ public Textifier() { - this(/* latest api = */ Opcodes.ASM8); + this(/* latest api = */ Opcodes.ASM9); if (getClass() != Textifier.class) { throw new IllegalStateException(); } @@ -153,8 +154,8 @@ public class Textifier extends Printer { * Constructs a new {@link Textifier}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link + * Opcodes#ASM8} or {@link Opcodes#ASM9}. */ protected Textifier(final int api) { super(api); @@ -163,7 +164,7 @@ public class Textifier extends Printer { /** * Prints a disassembled view of the given class to the standard output. * - *

    Usage: Textifier [-debug] <binary class name or class file name > + *

    Usage: Textifier [-nodebug] <binary class name or class file name > * * @param args the command line arguments. * @throws IOException if the class cannot be found, or if an IOException occurs. @@ -175,7 +176,7 @@ public class Textifier extends Printer { /** * Prints a disassembled view of the given class to the given output. * - *

    Usage: Textifier [-debug] <binary class name or class file name > + *

    Usage: Textifier [-nodebug] <binary class name or class file name > * * @param args the command line arguments. * @param output where to print the result. @@ -337,15 +338,8 @@ public class Textifier extends Printer { text.add(stringBuilder.toString()); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { + public void visitPermittedSubclass(final String permittedSubclass) { stringBuilder.setLength(0); stringBuilder.append(tab).append("PERMITTEDSUBCLASS "); appendDescriptor(INTERNAL_NAME, permittedSubclass); @@ -1638,3 +1632,4 @@ public class Textifier extends Printer { return new Textifier(api); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TextifierSupport.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TextifierSupport.java index f4a0c2cabd9c13365933cee26352e905bbd2b5b4..edc3bf0351b168ba9d106da41f4a61f38efe71ca 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TextifierSupport.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TextifierSupport.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.util.Map; @@ -76,3 +77,4 @@ public interface TextifierSupport { */ void textify(StringBuilder outputBuilder, Map labelNames); } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java index e13cb331134add26662e509806c683158182692e..9133b45c5639f4a01a970e32985555ffc462b660 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -88,7 +89,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor { * @param printer the printer to convert the visited annotation into text. */ public TraceAnnotationVisitor(final AnnotationVisitor annotationVisitor, final Printer printer) { - super(/* latest api = */ Opcodes.ASM8, annotationVisitor); + super(/* latest api = */ Opcodes.ASM9, annotationVisitor); this.printer = printer; } @@ -122,3 +123,4 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java index f8b20180d68cf11a8b2e524c5abfc939c3a70ed5..eade2bc9c479b476adf64f07af8cfbd718c559f2 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.io.PrintWriter; @@ -148,10 +149,9 @@ public final class TraceClassVisitor extends ClassVisitor { * @param printer the printer to convert the visited class into text. * @param printWriter the print writer to be used to print the class. May be {@literal null}. */ - @SuppressWarnings("deprecation") public TraceClassVisitor( final ClassVisitor classVisitor, final Printer printer, final PrintWriter printWriter) { - super(/* latest api = */ Opcodes.ASM9_EXPERIMENTAL, classVisitor); + super(/* latest api = */ Opcodes.ASM9, classVisitor); this.printWriter = printWriter; this.p = printer; } @@ -219,17 +219,10 @@ public final class TraceClassVisitor extends ClassVisitor { super.visitNestMember(nestMember); } - /** - * Experimental, use at your own risk.. - * - * @param permittedSubclass the internal name of a permitted subclass. - * @deprecated this API is experimental. - */ @Override - @Deprecated - public void visitPermittedSubclassExperimental(final String permittedSubclass) { - p.visitPermittedSubclassExperimental(permittedSubclass); - super.visitPermittedSubclassExperimental(permittedSubclass); + public void visitPermittedSubclass(final String permittedSubclass) { + p.visitPermittedSubclass(permittedSubclass); + super.visitPermittedSubclass(permittedSubclass); } @Override @@ -281,3 +274,4 @@ public final class TraceClassVisitor extends ClassVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java index 04f079d204499903e753f70ab7976eb5830fbd73..62cc5939f11dfc2ef80150eb08cca4d267b2b934 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -91,7 +92,7 @@ public final class TraceFieldVisitor extends FieldVisitor { * @param printer the printer to convert the visited field into text. */ public TraceFieldVisitor(final FieldVisitor fieldVisitor, final Printer printer) { - super(/* latest api = */ Opcodes.ASM8, fieldVisitor); + super(/* latest api = */ Opcodes.ASM9, fieldVisitor); this.p = printer; } @@ -122,3 +123,4 @@ public final class TraceFieldVisitor extends FieldVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java index 610bd94d7bbc92121b15f908511ce555d935d49c..6f58868694b01fed69513deee22722209b12cb90 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -93,7 +94,7 @@ public final class TraceMethodVisitor extends MethodVisitor { * @param printer the printer to convert the visited method into text. */ public TraceMethodVisitor(final MethodVisitor methodVisitor, final Printer printer) { - super(/* latest api = */ Opcodes.ASM8, methodVisitor); + super(/* latest api = */ Opcodes.ASM9, methodVisitor); this.p = printer; } @@ -341,3 +342,4 @@ public final class TraceMethodVisitor extends MethodVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java index b9e29c919ce671a5ef210cb4de7172dd57b2798e..cbd0bf7aca7476b9bf3beb3699fe9877f2bb13d7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.ModuleVisitor; @@ -88,7 +89,7 @@ public final class TraceModuleVisitor extends ModuleVisitor { * @param printer the printer to convert the visited module into text. */ public TraceModuleVisitor(final ModuleVisitor moduleVisitor, final Printer printer) { - super(/* latest api = */ Opcodes.ASM8, moduleVisitor); + super(/* latest api = */ Opcodes.ASM9, moduleVisitor); this.p = printer; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceRecordComponentVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceRecordComponentVisitor.java index 70e2a0258c83365bdbc01a70f8c69031767c2f00..2069f299d1a29a3f3488b467b3fa042efb67d2c1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceRecordComponentVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceRecordComponentVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -93,7 +94,7 @@ public final class TraceRecordComponentVisitor extends RecordComponentVisitor { */ public TraceRecordComponentVisitor( final RecordComponentVisitor recordComponentVisitor, final Printer printer) { - super(/* latest api ='*/ Opcodes.ASM8, recordComponentVisitor); + super(/* latest api ='*/ Opcodes.ASM9, recordComponentVisitor); this.printer = printer; } @@ -125,3 +126,4 @@ public final class TraceRecordComponentVisitor extends RecordComponentVisitor { super.visitEnd(); } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java index c9d41729852f27890bce544a0ea502e74590b2ce..a7ba0fb6a0f1aa6cdb3fac56e26ee50f95ef4edc 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java @@ -56,6 +56,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ + package jdk.internal.org.objectweb.asm.util; import java.util.Collections; @@ -140,13 +141,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor { * @param accessFlags for class type signatures, the access flags of the class. */ public TraceSignatureVisitor(final int accessFlags) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.isInterface = (accessFlags & Opcodes.ACC_INTERFACE) != 0; this.declaration = new StringBuilder(); } private TraceSignatureVisitor(final StringBuilder stringBuilder) { - super(/* latest api = */ Opcodes.ASM8); + super(/* latest api = */ Opcodes.ASM9); this.isInterface = false; this.declaration = stringBuilder; } @@ -256,7 +257,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor { @Override public void visitClassType(final String name) { if ("java/lang/Object".equals(name)) { - // 'Map' or 'public abstract V get(Object key);' should have + // 'Map' or 'abstract public V get(Object key);' should have // Object 'but java.lang.String extends java.lang.Object' is unnecessary. boolean needObjectClass = argumentStack % 2 != 0 || parameterTypeVisited; if (needObjectClass) { @@ -373,3 +374,4 @@ public final class TraceSignatureVisitor extends SignatureVisitor { } } } + diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt index 023148eacfef8f8937ec7f7d50dea488e9bf3b17..b35c1bbf9edb7c6e96010e0d438b203b4504c42d 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt @@ -1,2 +1,2 @@ -ASM_8_0_1 +ASM_9_2 origin http://gitlab.ow2.org/asm/asm.git (fetch) diff --git a/src/java.base/share/classes/jdk/internal/reflect/SignatureIterator.java b/src/java.base/share/classes/jdk/internal/reflect/SignatureIterator.java deleted file mode 100644 index ca5c8b78a7215bdf2e1d90f018ea9320fa80e8d4..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/jdk/internal/reflect/SignatureIterator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.reflect; - -/** Assists in iterating down a method's signature */ - -class SignatureIterator { - private final String sig; - private int idx; - - public SignatureIterator(String sig) { - this.sig = sig; - reset(); - } - - public void reset() { - idx = 1; - } - - public boolean atEnd() { - return sig.charAt(idx) == ')'; - } - - public String next() { - if (atEnd()) return null; - char c = sig.charAt(idx); - if (c != '[' && c != 'L') { - ++idx; - return String.valueOf(c); - } - // Walk forward to end of entry - int endIdx = idx; - if (c == '[') { - while ((c = sig.charAt(endIdx)) == '[') { - endIdx++; - } - } - - if (c == 'L') { - while (sig.charAt(endIdx) != ';') { - endIdx++; - } - } - - int beginIdx = idx; - idx = endIdx + 1; - return sig.substring(beginIdx, idx); - } - - /** Should only be called when atEnd() is true. Does not change - state of iterator. */ - public String returnType() { - if (!atEnd()) { - throw new InternalError("Illegal use of SignatureIterator"); - } - return sig.substring(idx + 1, sig.length()); - } -} 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/launcher/resources/launcher_de.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties index 85c7ead75fba60c437d164a2d3da7481495edcc5..7edc4b1685118b7122237625fb3f84c6f88fa89b 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -24,21 +24,21 @@ # # Translators please note do not translate the options themselves -java.launcher.opt.header = Verwendung: {0} [Optionen] [args...]\n (zur Ausf\u00FChrung einer Klasse)\n oder {0} [Optionen] -jar [args...]\n (zur Ausf\u00FChrung einer JAR-Datei)\n oder {0} [Optionen] -m [/] [args...]\n {0} [Optionen] --module [/] [args...]\n (zur Ausf\u00FChrung der Hauptklasse in einem Modul)\n\n Argumente, die auf die Hauptklasse folgen, -jar , -m oder --module\n / werden als Argumente f\u00FCr die Hauptklasse \u00FCbergeben.\n\n wobei "Optionen" Folgendes umfasst:\n\n +java.launcher.opt.header = Verwendung: {0} [Optionen] [args...]\n (zur Ausf\u00FChrung einer Klasse)\n oder {0} [Optionen] -jar [args...]\n (zur Ausf\u00FChrung einer JAR-Datei)\n oder {0} [Optionen] -m [/] [args...]\n {0} [Optionen] --module [/] [args...]\n (zur Ausf\u00FChrung der Hauptklasse in einem Modul)\n oder {0} [Optionen] [args]\n (zur Ausf\u00FChrung eines Programms mit einer einzelnen Quelldatei)\n\n Argumente, die auf die Hauptklasse, die Quelldatei, -jar , -m oder --module\n / folgen, werden als Argumente f\u00FCr die\nHauptklasse \u00FCbergeben.\n\n Dabei umfasst "Optionen" Folgendes:\n\n java.launcher.opt.vmselect =\ {0}\t zur Auswahl der "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t ist ein Synonym f\u00FCr die "{1}" VM [verworfen]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch {0} getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch {0} getrennte Liste mit Verzeichnissen, von denen jedes Verzeichnis\n ein Verzeichnis mit Modulen ist.\n --upgrade-module-path ...\n Eine durch {0} getrennte Liste mit Verzeichnissen, von denen jedes Verzeichnis\n ein Verzeichnis mit Modulen ist, die upgradef\u00E4hige\n Module im Laufzeitimage ersetzen\n --add-modules [,...]\n Root-Module, die zus\u00E4tzlich zum anf\u00E4nglichen Modul aufgel\u00F6st werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und l\u00E4dt die Hauptklasse, f\u00FChrt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann n\u00FCtzlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann n\u00FCtzlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Ausgabe im Verbose-Modus aktivieren\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulaufl\u00F6sungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zus\u00E4tzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zus\u00E4tzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener Granularit\u00E4t\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularit\u00E4t\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n L\u00E4dt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n L\u00E4dt die native Agent Library mit dem vollst\u00E4ndigen Pfadnamen\n -javaagent:[=]\n L\u00E4dt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch \ -unterst\u00FCtzt und verwendet,\n falls verf\u00FCgbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" \u00FCbergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgew\u00E4hlt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n -disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\nUm ein Argument f\u00FCr eine lange Option anzugeben, k\u00F6nnen Sie --= oder\n-- verwenden.\n +java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch {0} getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch {0} getrennte Liste mit Verzeichnissen, von denen jedes Verzeichnis\n ein Verzeichnis mit Modulen ist.\n --upgrade-module-path ...\n Eine durch {0} getrennte Liste mit Verzeichnissen, von denen jedes Verzeichnis\n ein Verzeichnis mit Modulen ist, die upgradef\u00E4hige\n Module im Laufzeitimage ersetzen\n --add-modules [,...]\n Root-Module, die zus\u00E4tzlich zum anf\u00E4nglichen Modul aufgel\u00F6st werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n Module, die eingeschr\u00E4nkte native Vorg\u00E4nge ausf\u00FChren d\u00FCrfen.\n kann auch ALL-UNNAMED lauten.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und l\u00E4dt die Hauptklasse, f\u00FChrt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann n\u00FCtzlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann n\u00FCtzlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Aktiviert die Verbose-Ausgabe f\u00FCr das angegebene Subsystem\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulaufl\u00F6sungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zus\u00E4tzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zus\u00E4tzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener Granularit\u00E4t\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularit\u00E4t\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n L\u00E4dt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n L\u00E4dt die native Agent Library mit dem vollst\u00E4ndigen Pfadnamen\n -javaagent:[=]\n \ +L\u00E4dt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterst\u00FCtzt und verwendet,\n falls verf\u00FCgbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" \u00FCbergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgew\u00E4hlt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n -disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n L\u00E4sst zu, das Klassen von Vorschaufeatures dieses Release abh\u00E4ngig sind\nUm ein Argument f\u00FCr eine lange Option anzugeben, k\u00F6nnen Sie --= oder\n-- verwenden.\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch Deaktiviert Hintergrundkompilierung\n -Xbootclasspath/a:\n an Ende von Bootstrap Classpath anh\u00E4ngen\n -Xcheck:jni F\u00FChrt zus\u00E4tzliche Pr\u00FCfungen f\u00FCr JNI-Funktionen aus\n -Xcomp Erzwingt Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Wird zur Abw\u00E4rtskompatibilit\u00E4t bereitgestellt\n -Xdiag Zeigt zus\u00E4tzliche Diagnosemeldungen an\n -Xfuture Aktiviert strengste Pr\u00FCfungen, wird als m\u00F6glicher zuk\u00FCnftiger Standardwert erwartet\n -Xint Nur Ausf\u00FChrung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option "-version"\n -Xloggc: Protokolliert GC-Status in einer Datei mit Zeitstempeln\n -Xmixed Ausf\u00FChrung im gemischten Modus (Standard)\n -Xmn Legt die anf\u00E4ngliche und die maximale Gr\u00F6\u00DFe (in Byte) des Heaps\n f\u00FCr die Young Generation (Nursery) fest\n -Xms Legt die anf\u00E4ngliche Java-Heap-Gr\u00F6\u00DFe fest\n -Xmx Legt die maximale Java-Heap-Gr\u00F6\u00DFe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet, wenn m\u00F6glich, freigegebene Klassendaten (Standard)\n -Xshare:off Versucht nicht freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung von freigegebenen Klassendaten, verl\u00E4uft sonst nicht erfolgreich.\n -XshowSettings Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:all\n Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und f\u00E4hrt fort\n -XshowSettings:vm Zeigt alle VM-bezogenen Einstellungen an und f\u00E4hrt fort\n -Xss Legt Stackgr\u00F6\u00DFe des Java-Threads fest\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n --add-reads =(,)*\n Aktualisiert , damit ungeachtet der\n Moduldeklaration gelesen wird.\n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um ungeachtet der Moduldeklaration in \n zu exportieren.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um ungeachtet der Moduldeklaration in\n zu \u00F6ffnen.\n --illegal-access=\n L\u00E4sst Zugriff f\u00FCr Mitglieder mit den Typen in den benannten Modulen\n nach Code in unbenannten Modulen zu oder lehnt ihn ab.\n ist entweder "deny", "permit", "warn" oder "debug"\n Diese Option wird in einem zuk\u00FCnftigen Release entfernt.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n \u00DCberschreibt oder erweitert ein Modul in JAR-Dateien\n oder -Verzeichnissen mit \ -Klassen und Ressourcen.\n --disable-@files Deaktiviert die weitere Erweiterung von Argumentdateien\n\nDiese zus\u00E4tzlichen Optionen k\u00F6nnen ohne Vorank\u00FCndigung ge\u00E4ndert werden.\n +java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anh\u00E4ngen\n -Xcheck:jni F\u00FChrt zus\u00E4tzliche Pr\u00FCfungen f\u00FCr JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug F\u00FChrt nichts aus. Wird aus Gr\u00FCnden der Abw\u00E4rtskompatibilit\u00E4t bereitgestellt.\n -Xdiag Zeigt zus\u00E4tzliche Diagnosemeldungen an\n -Xfuture Aktiviert strengste Pr\u00FCfungen, als m\u00F6glicher zuk\u00FCnftiger Standardwert erwartet.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden.\n -Xint Nur Ausf\u00FChrung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n f\u00FCr weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausf\u00FChrung im gemischten Modus (Standard)\n -Xmn Legt die anf\u00E4ngliche und maximale Gr\u00F6\u00DFe (in Byte) des Heaps\n f\u00FCr die Young Generation (Nursery) fest\n -Xms Legt die anf\u00E4ngliche Java-Heap-Gr\u00F6\u00DFe fest\n -Xmx Legt die maximale Java-Heap-Gr\u00F6\u00DFe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn m\u00F6glich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verl\u00E4uft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern f\u00FChren. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:all\n Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und f\u00E4hrt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und f\u00E4hrt fort\n -Xss Legt die Stackgr\u00F6\u00DFe des Java-Threads fest\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zuk\u00FCnftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in \ + zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu \u00F6ffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n \u00DCberschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardm\u00E4\u00DFig aktiviert.\n\nDiese zus\u00E4tzlichen Optionen k\u00F6nnen jederzeit ohne vorherige Ank\u00FCndigung ge\u00E4ndert werden.\n # Translators please note do not translate the options themselves -java.launcher.X.macosx.usage=\nDie folgenden Optionen sind f\u00FCr Mac OS X spezifisch:\n -XstartOnFirstThread\n main()-Methode f\u00FCr den ersten (AppKit) Thread ausf\u00FChren\n -Xdock:name=\n Den im Dock angezeigten Standardanwendungsnamen \u00FCberschreiben\n -Xdock:icon=\n Das im Dock angezeigte Standardsymbol \u00FCberschreiben\n\n +java.launcher.X.macosx.usage=\nDie folgenden Optionen sind f\u00FCr macOS spezifisch:\n -XstartOnFirstThread\n F\u00FChrt die main()-Methode f\u00FCr den ersten (AppKit-)Thread aus\n -Xdock:name=\n Setzt den im Dock angezeigten Standardanwendungsnamen au\u00DFer Kraft\n -Xdock:icon=\n Setzt das im Dock angezeigte Standardsymbol au\u00DFer Kraft\n\n java.launcher.cls.error1=Fehler: Hauptklasse {0} konnte nicht gefunden oder geladen werden\nUrsache: {1}: {2} java.launcher.cls.error2=Fehler: Hauptmethode ist nicht {0} in Klasse {1}. Definieren Sie die Hauptmethode als:\n public static void main(String[] args) @@ -53,8 +53,8 @@ java.launcher.jar.error3=kein Hauptmanifestattribut, in {0} java.launcher.jar.error4=Fehler beim Laden des Java-Agents in {0} java.launcher.init.error=Initialisierungsfehler java.launcher.javafx.error1=Fehler: Die JavaFX-Methode launchApplication hat die falsche Signatur, sie\nmuss als statisch deklariert werden und einen Wert vom Typ VOID zur\u00FCckgeben -java.launcher.module.error1=Modul {0} weist kein MainClass-Attribut auf. Verwenden Sie -m / +java.launcher.module.error1=Modul {0} weist kein ModuleMainClass-Attribut auf. Verwenden Sie -m / java.launcher.module.error2=Fehler: Hauptklasse {0} konnte in Modul {1} nicht gefunden oder geladen werden java.launcher.module.error3=Fehler: Hauptklasse {0} kann nicht in Modul {1} geladen werden\n\t{2} java.launcher.module.error4={0} nicht gefunden -java.launcher.module.error5=Fehler: Hauptklasse {0} kann nicht in Modul {1} initialisiert werden\nUrsache: {1}: {2} +java.launcher.module.error5=Fehler: Hauptklasse {0} kann nicht in Modul {1} initialisiert werden\nUrsache: {2}: {3} diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties index 32d28144dff7602fa351aa8ac684267002544d8e..542145ccbb04f2844828475188f5d7edee68f360 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -30,14 +30,14 @@ java.launcher.opt.vmselect =\ {0}\t "{1}" VM\u3092\u9078\u629E\u3059\u308B java.launcher.opt.hotspot =\ {0}\t \u306F"{1}" VM\u306E\u30B7\u30CE\u30CB\u30E0\u3067\u3059 [\u975E\u63A8\u5968]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n -classpath <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n --class-path <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n {0}\u533A\u5207\u308A\u30EA\u30B9\u30C8(\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3001JAR\u30A2\u30FC\u30AB\u30A4\u30D6\u3001\n ZIP\u30A2\u30FC\u30AB\u30A4\u30D6)\u3067\u3001\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u7D22\u7528\u3002\n -p \n --module-path ...\n \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E{0}\u533A\u5207\u308A\u30EA\u30B9\u30C8\u3001\u5404\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n \u306F\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3059\u3002\n --upgrade-module-path ...\n \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E{0}\u533A\u5207\u308A\u30EA\u30B9\u30C8\u3001\u5404\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n \u306F\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u5185\u306E\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u53EF\u80FD\u306A\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7F6E\u63DB\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3059\n --add-modules [,...]\n \u521D\u671F\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\u52A0\u3048\u3066\u89E3\u6C7A\u3059\u308B\u30EB\u30FC\u30C8\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\n \u306B\u306F\u6B21\u3082\u6307\u5B9A\u3067\u304D\u307E\u3059: ALL-DEFAULT\u3001ALL-SYSTEM\u3001\n ALL-MODULE-PATH.\n --list-modules\n \u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30EA\u30B9\u30C8\u3057\u7D42\u4E86\u3057\u307E\u3059\n -d \n --describe-module \n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u8AAC\u660E\u3057\u7D42\u4E86\u3057\u307E\u3059\n --dry-run VM\u3092\u4F5C\u6210\u3057\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u304C\u3001\u30E1\u30A4\u30F3\u30FB\u30E1\u30BD\u30C3\u30C9\u306F\u5B9F\u884C\u3057\u307E\u305B\u3093\u3002\n --dry-run\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u3001\u6B21\u306E\u691C\u8A3C\u306B\u5F79\u7ACB\u3064\u5834\u5408\u304C\u3042\u308A\u307E\u3059:\n \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30B7\u30B9\u30C6\u30E0\u69CB\u6210\u306A\u3069\u306E\u30B3\u30DE\u30F3\u30C9\u884C\u30AA\u30D7\u30B7\u30E7\u30F3\u3002\n --validate-modules\n \u3059\u3079\u3066\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u691C\u8A3C\u3057\u7D42\u4E86\u3057\u307E\u3059\n --validate-modules\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u3001\u6B21\u306E\u691C\u7D22\u306B\u5F79\u7ACB\u3064\u5834\u5408\u304C\u3042\u308A\u307E\u3059:\n \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D1\u30B9\u4E0A\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u3067\u306E\u7AF6\u5408\u304A\u3088\u3073\u305D\u306E\u4ED6\u306E\u30A8\u30E9\u30FC\u3002\n -D=\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -verbose:[class|module|gc|jni]\n \u7279\u5B9A\u306E\u30B5\u30D6\u30B7\u30B9\u30C6\u30E0\u3067\u8A73\u7D30\u51FA\u529B\u3092\u6709\u52B9\u306B\u3059\u308B\n -version \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\n --version \ -\u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\n -showversion \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n --show-version\n \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n --show-module-resolution\n \u8D77\u52D5\u6642\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u89E3\u6C7A\u51FA\u529B\u3092\u8868\u793A\u3057\u307E\u3059\n -? -h -help\n \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n --help \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n -X \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n --help-extra \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n -ea[:...|:]\n -enableassertions[:...|:]\n \u6307\u5B9A\u3057\u305F\u7C92\u5EA6\u3067\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n -da[:...|:]\n -disableassertions[:...|:]\n \u6307\u5B9A\u3057\u305F\u7C92\u5EA6\u3067\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -esa | -enablesystemassertions\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n -dsa | -disablesystemassertions\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -agentlib:[=]\n \u30CD\u30A4\u30C6\u30A3\u30D6\u30FB\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30E9\u30A4\u30D6\u30E9\u30EA\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u3002\u4F8B: -agentlib:jdwp\n -agentlib:jdwp=help\u3082\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n -agentpath:[=]\n \u30D5\u30EB\u30D1\u30B9\u540D\u3092\u4F7F\u7528\u3057\u3066\u3001\u30CD\u30A4\u30C6\u30A3\u30D6\u30FB\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30E9\u30A4\u30D6\u30E9\u30EA\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\n -javaagent:[=]\n Java\u30D7\u30ED\u30B0\u30E9\u30DF\u30F3\u30B0\u8A00\u8A9E\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u3002java.lang.instrument\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n -splash:\n \u6307\u5B9A\u3055\u308C\u305F\u30A4\u30E1\u30FC\u30B8\u3092\u542B\u3080\u30B9\u30D7\u30E9\u30C3\u30B7\u30E5\u753B\u9762\u3092\u8868\u793A\u3057\u307E\u3059\n HiDPI\u30B9\u30B1\u30FC\u30EB\u306E\u30A4\u30E1\u30FC\u30B8\u304C\u81EA\u52D5\u7684\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\n (\u53EF\u80FD\u306A\u5834\u5408)\u3002\u30B9\u30B1\u30FC\u30EA\u30F3\u30B0\u3055\u308C\u306A\u3044\u30A4\u30E1\u30FC\u30B8\u306E\u30D5\u30A1\u30A4\u30EB\u540D(image.ext\u306A\u3069)\u3092\n \u5F15\u6570\u3068\u3057\u3066-splash\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u5FC5\u305A\u6E21\u3059\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n \ -\u6307\u5B9A\u3055\u308C\u305F\u6700\u3082\u9069\u5207\u306A\u30B9\u30B1\u30FC\u30EA\u30F3\u30B0\u6E08\u30A4\u30E1\u30FC\u30B8\u304C\u9078\u629E\u3055\u308C\u307E\u3059\n (\u81EA\u52D5\u7684)\u3002\n \u8A73\u7D30\u306F\u3001SplashScreen API\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n @argument\u30D5\u30A1\u30A4\u30EB\n \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u542B\u30801\u3064\u4EE5\u4E0A\u306E\u5F15\u6570\u30D5\u30A1\u30A4\u30EB\n -disable-@files\n \u3055\u3089\u306A\u308B\u5F15\u6570\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n --enable-preview\n \u30AF\u30E9\u30B9\u3092\u3053\u306E\u30EA\u30EA\u30FC\u30B9\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u306B\u4F9D\u5B58\u3055\u305B\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\n\u9577\u3044\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5F15\u6570\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u3001--=\u307E\u305F\u306F\n-- \u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n +java.launcher.opt.footer = \ -cp <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n -classpath <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n --class-path <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\u3088\u3073zip/jar\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30E9\u30B9\u691C\u7D22\u30D1\u30B9>\n {0}\u533A\u5207\u308A\u30EA\u30B9\u30C8(\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3001JAR\u30A2\u30FC\u30AB\u30A4\u30D6\u3001\n ZIP\u30A2\u30FC\u30AB\u30A4\u30D6)\u3067\u3001\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u7D22\u7528\u3002\n -p \n --module-path ...\n \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E{0}\u533A\u5207\u308A\u30EA\u30B9\u30C8\u3001\u5404\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n \u306F\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3059\u3002\n --upgrade-module-path ...\n \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E{0}\u533A\u5207\u308A\u30EA\u30B9\u30C8\u3001\u5404\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n \u306F\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u5185\u306E\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u53EF\u80FD\u306A\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7F6E\u63DB\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3059\n --add-modules [,...]\n \u521D\u671F\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\u52A0\u3048\u3066\u89E3\u6C7A\u3059\u308B\u30EB\u30FC\u30C8\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\n \u306B\u306F\u6B21\u3082\u6307\u5B9A\u3067\u304D\u307E\u3059: ALL-DEFAULT\u3001ALL-SYSTEM\u3001\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n \u5236\u9650\u3055\u308C\u305F\u30CD\u30A4\u30C6\u30A3\u30D6\u64CD\u4F5C\u306E\u5B9F\u884C\u3092\u8A31\u53EF\u3055\u308C\u3066\u3044\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\n \u306FALL-UNNAMED\u306B\u3059\u308B\u3053\u3068\u3082\u3067\u304D\u307E\u3059\u3002\n --list-modules\n \u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30EA\u30B9\u30C8\u3057\u7D42\u4E86\u3057\u307E\u3059\n -d \n --describe-module \n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u8AAC\u660E\u3057\u7D42\u4E86\u3057\u307E\u3059\n --dry-run VM\u3092\u4F5C\u6210\u3057\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u304C\u3001\u30E1\u30A4\u30F3\u30FB\u30E1\u30BD\u30C3\u30C9\u306F\u5B9F\u884C\u3057\u307E\u305B\u3093\u3002\n --dry-run\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u3001\u6B21\u306E\u691C\u8A3C\u306B\u5F79\u7ACB\u3064\u5834\u5408\u304C\u3042\u308A\u307E\u3059:\n \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30B7\u30B9\u30C6\u30E0\u69CB\u6210\u306A\u3069\u306E\u30B3\u30DE\u30F3\u30C9\u884C\u30AA\u30D7\u30B7\u30E7\u30F3\u3002\n --validate-modules\n \u3059\u3079\u3066\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u691C\u8A3C\u3057\u7D42\u4E86\u3057\u307E\u3059\n --validate-modules\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u3001\u6B21\u306E\u691C\u7D22\u306B\u5F79\u7ACB\u3064\u5834\u5408\u304C\u3042\u308A\u307E\u3059:\n \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D1\u30B9\u4E0A\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u3067\u306E\u7AF6\u5408\u304A\u3088\u3073\u305D\u306E\u4ED6\u306E\u30A8\u30E9\u30FC\u3002\n -D=\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -verbose:[class|module|gc|jni]\n \ +\u7279\u5B9A\u306E\u30B5\u30D6\u30B7\u30B9\u30C6\u30E0\u3067\u8A73\u7D30\u51FA\u529B\u3092\u6709\u52B9\u306B\u3059\u308B\n -version \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\n --version \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\n -showversion \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n --show-version\n \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n --show-module-resolution\n \u8D77\u52D5\u6642\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u89E3\u6C7A\u51FA\u529B\u3092\u8868\u793A\u3057\u307E\u3059\n -? -h -help\n \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n --help \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n -X \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u30A8\u30E9\u30FC\u30FB\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n --help-extra \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u307E\u3059\n -ea[:...|:]\n -enableassertions[:...|:]\n \u6307\u5B9A\u3057\u305F\u7C92\u5EA6\u3067\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n -da[:...|:]\n -disableassertions[:...|:]\n \u6307\u5B9A\u3057\u305F\u7C92\u5EA6\u3067\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -esa | -enablesystemassertions\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n -dsa | -disablesystemassertions\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -agentlib:[=]\n \u30CD\u30A4\u30C6\u30A3\u30D6\u30FB\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30E9\u30A4\u30D6\u30E9\u30EA\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u3002\u4F8B: -agentlib:jdwp\n -agentlib:jdwp=help\u3082\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n -agentpath:[=]\n \u30D5\u30EB\u30D1\u30B9\u540D\u3092\u4F7F\u7528\u3057\u3066\u3001\u30CD\u30A4\u30C6\u30A3\u30D6\u30FB\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30E9\u30A4\u30D6\u30E9\u30EA\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\n -javaagent:[=]\n Java\u30D7\u30ED\u30B0\u30E9\u30DF\u30F3\u30B0\u8A00\u8A9E\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3092\u30ED\u30FC\u30C9\u3057\u307E\u3059\u3002java.lang.instrument\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n -splash:\n \u6307\u5B9A\u3055\u308C\u305F\u30A4\u30E1\u30FC\u30B8\u3092\u542B\u3080\u30B9\u30D7\u30E9\u30C3\u30B7\u30E5\u753B\u9762\u3092\u8868\u793A\u3057\u307E\u3059\n HiDPI\u30B9\u30B1\u30FC\u30EB\u306E\u30A4\u30E1\u30FC\u30B8\u304C\u81EA\u52D5\u7684\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\n \ +(\u53EF\u80FD\u306A\u5834\u5408)\u3002\u30B9\u30B1\u30FC\u30EA\u30F3\u30B0\u3055\u308C\u306A\u3044\u30A4\u30E1\u30FC\u30B8\u306E\u30D5\u30A1\u30A4\u30EB\u540D(image.ext\u306A\u3069)\u3092\n \u5F15\u6570\u3068\u3057\u3066-splash\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u5FC5\u305A\u6E21\u3059\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n \u6307\u5B9A\u3055\u308C\u305F\u6700\u3082\u9069\u5207\u306A\u30B9\u30B1\u30FC\u30EA\u30F3\u30B0\u6E08\u30A4\u30E1\u30FC\u30B8\u304C\u9078\u629E\u3055\u308C\u307E\u3059\n (\u81EA\u52D5\u7684)\u3002\n \u8A73\u7D30\u306F\u3001SplashScreen API\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\n @argument\u30D5\u30A1\u30A4\u30EB\n \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u542B\u30801\u3064\u4EE5\u4E0A\u306E\u5F15\u6570\u30D5\u30A1\u30A4\u30EB\n -disable-@files\n \u3055\u3089\u306A\u308B\u5F15\u6570\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n --enable-preview\n \u30AF\u30E9\u30B9\u3092\u3053\u306E\u30EA\u30EA\u30FC\u30B9\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u306B\u4F9D\u5B58\u3055\u305B\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\n\u9577\u3044\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5F15\u6570\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u3001--=\u307E\u305F\u306F\n-- \u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch \u30D0\u30C3\u30AF\u30B0\u30E9\u30A6\u30F3\u30C9\u30FB\u30B3\u30F3\u30D1\u30A4\u30EB\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -Xbootclasspath/a:\n \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306E\u6700\u5F8C\u306B\u8FFD\u52A0\u3057\u307E\u3059\n -Xcheck:jni JNI\u95A2\u6570\u306B\u5BFE\u3059\u308B\u8FFD\u52A0\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u5B9F\u884C\u3057\u307E\u3059\n -Xcomp \u521D\u56DE\u547C\u51FA\u3057\u6642\u306B\u30E1\u30BD\u30C3\u30C9\u306E\u30B3\u30F3\u30D1\u30A4\u30EB\u3092\u5F37\u5236\u3057\u307E\u3059\n -Xdebug \u4F55\u3082\u884C\u3044\u307E\u305B\u3093\u3002\u4E0B\u4F4D\u4E92\u63DB\u6027\u306E\u305F\u3081\u306B\u7528\u610F\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n -Xdiag \u8FFD\u52A0\u306E\u8A3A\u65AD\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059\n -Xfuture \u5C06\u6765\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u898B\u8D8A\u3057\u3066\u3001\u6700\u3082\u53B3\u5BC6\u306A\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n -Xint \u30A4\u30F3\u30BF\u30D7\u30EA\u30BF\u30FB\u30E2\u30FC\u30C9\u306E\u5B9F\u884C\u306E\u307F\n -Xinternalversion\n -version\u30AA\u30D7\u30B7\u30E7\u30F3\u3088\u308A\u8A73\u7D30\u306AJVM\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\n \u8868\u793A\u3057\u307E\u3059\n -Xlog: Java Virtual Machine (JVM)\u7D71\u5408\u30ED\u30AE\u30F3\u30B0\u30FB\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u3067\u306E\n \u30ED\u30AE\u30F3\u30B0\u3092\u69CB\u6210\u307E\u305F\u306F\u6709\u52B9\u5316\u3057\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001-Xlog:help\u3092\n \u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n -Xloggc: \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u4ED8\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u306BGC\u30B9\u30C6\u30FC\u30BF\u30B9\u306E\u30ED\u30B0\u3092\u8A18\u9332\u3057\u307E\u3059\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002-Xlog:gc:\u3067\u7F6E\u63DB\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n -Xmixed \u6DF7\u5408\u30E2\u30FC\u30C9\u306E\u5B9F\u884C(\u30C7\u30D5\u30A9\u30EB\u30C8)\n -Xmn \u82E5\u3044\u4E16\u4EE3(\u30CA\u30FC\u30B5\u30EA)\u306E\u30D2\u30FC\u30D7\u306E\u521D\u671F\u30B5\u30A4\u30BA\u304A\u3088\u3073\u6700\u5927\u30B5\u30A4\u30BA\n (\u30D0\u30A4\u30C8\u5358\u4F4D)\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xms Java\u306E\u521D\u671F\u30D2\u30FC\u30D7\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xmx Java\u306E\u6700\u5927\u30D2\u30FC\u30D7\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xnoclassgc \u30AF\u30E9\u30B9\u306E\u30AC\u30D9\u30FC\u30B8\u30FB\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -Xrs Java/VM\u306B\u3088\u308BOS\u30B7\u30B0\u30CA\u30EB\u306E\u4F7F\u7528\u3092\u524A\u6E1B\u3057\u307E\u3059(\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u53C2\u7167)\n -Xshare:auto \u53EF\u80FD\u3067\u3042\u308C\u3070\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8)\n -Xshare:off \ -\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u8A66\u307F\u307E\u305B\u3093\n -Xshare:on \u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u5FC5\u9808\u306B\u3057\u3001\u3067\u304D\u306A\u3051\u308C\u3070\u5931\u6557\u3057\u307E\u3059\u3002\n \u3053\u308C\u306F\u30C6\u30B9\u30C8\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u3001\u65AD\u7D9A\u7684\u306A\u5931\u6557\u306B\u3064\u306A\u304C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u672C\u756A\u74B0\u5883\u3067\u306F\u4F7F\u7528\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n -XshowSettings \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:all\n \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:locale\n \u3059\u3079\u3066\u306E\u30ED\u30B1\u30FC\u30EB\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:properties\n \u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:vm\n \u3059\u3079\u3066\u306EVM\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:system\n (Linux\u306E\u307F)\u30DB\u30B9\u30C8\u30FB\u30B7\u30B9\u30C6\u30E0\u307E\u305F\u306F\u30B3\u30F3\u30C6\u30CA\u3092\u8868\u793A\u3057\u307E\u3059\n \u69CB\u6210\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -Xss java\u30B9\u30EC\u30C3\u30C9\u306E\u30B9\u30BF\u30C3\u30AF\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xverify \u30D0\u30A4\u30C8\u30B3\u30FC\u30C9\u30FB\u30D9\u30EA\u30D5\u30A1\u30A4\u30A2\u306E\u30E2\u30FC\u30C9\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n \u30AA\u30D7\u30B7\u30E7\u30F3-Xverify:none\u306F\u975E\u63A8\u5968\u306B\u306A\u308A\u3001\n \u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n --add-reads =(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u8AAD\u307F\u53D6\u308A\u307E\u3059\u3002 \n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\n \u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\n --add-exports /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3067\u304D\u307E\u3059\u3002\n --add-opens /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u306B\u958B\u304D\u307E\u3059\u3002\n --illegal-access=\n \ -\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u5185\u306E\u30B3\u30FC\u30C9\u306B\u3088\u308B\u3001\u540D\u524D\u306E\u3042\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u5185\u306E\u30BF\u30A4\u30D7\u306E\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u4E0D\u6B63\u30A2\u30AF\u30BB\u30B9\u3092\n \u8A31\u53EF\u307E\u305F\u306F\u62D2\u5426\u3057\u307E\u3059\u3002\n \u306F"deny"\u3001"permit"\u3001"warn"\u307E\u305F\u306F"debug"\u306E\u3044\u305A\u308C\u304B\u3067\u3059\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059\u3002\n --limit-modules [,...]\n \u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9818\u57DF\u3092\u5236\u9650\u3057\u307E\u3059\n --patch-module =({0})*\n JAR\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30EA\u30BD\u30FC\u30B9\u3067\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u62E1\u5F35\u3057\u307E\u3059\u3002\n --source \n \u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u30FB\u30E2\u30FC\u30C9\u3067\u30BD\u30FC\u30B9\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\n\n\u3053\u306E\u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\n +\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u8A66\u307F\u307E\u305B\u3093\n -Xshare:on \u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u5FC5\u9808\u306B\u3057\u3001\u3067\u304D\u306A\u3051\u308C\u3070\u5931\u6557\u3057\u307E\u3059\u3002\n \u3053\u308C\u306F\u30C6\u30B9\u30C8\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u3001\u65AD\u7D9A\u7684\u306A\u5931\u6557\u306B\u3064\u306A\u304C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u672C\u756A\u74B0\u5883\u3067\u306F\u4F7F\u7528\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n -XshowSettings \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:all\n \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:locale\n \u3059\u3079\u3066\u306E\u30ED\u30B1\u30FC\u30EB\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:properties\n \u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:vm\n \u3059\u3079\u3066\u306EVM\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:system\n (Linux\u306E\u307F)\u30DB\u30B9\u30C8\u30FB\u30B7\u30B9\u30C6\u30E0\u307E\u305F\u306F\u30B3\u30F3\u30C6\u30CA\u3092\u8868\u793A\u3057\u307E\u3059\n \u69CB\u6210\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -Xss java\u30B9\u30EC\u30C3\u30C9\u306E\u30B9\u30BF\u30C3\u30AF\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xverify \u30D0\u30A4\u30C8\u30B3\u30FC\u30C9\u30FB\u30D9\u30EA\u30D5\u30A1\u30A4\u30A2\u306E\u30E2\u30FC\u30C9\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n \u30AA\u30D7\u30B7\u30E7\u30F3-Xverify:none\u306F\u975E\u63A8\u5968\u306B\u306A\u308A\u3001\n \u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n --add-reads =(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u8AAD\u307F\u53D6\u308A\u307E\u3059\u3002 \n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\n \u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\n --add-exports /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3067\u304D\u307E\u3059\u3002\n --add-opens /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u306B\u958B\u304D\u307E\u3059\u3002\n --limit-modules [,...]\n \ +\u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9818\u57DF\u3092\u5236\u9650\u3057\u307E\u3059\n --patch-module =({0})*\n JAR\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30EA\u30BD\u30FC\u30B9\u3067\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u62E1\u5F35\u3057\u307E\u3059\u3002\n --source \n \u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u30FB\u30E2\u30FC\u30C9\u3067\u30BD\u30FC\u30B9\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\n --finalization=\n JVM\u304C\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u3092\u5B9F\u884C\u3059\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059\n \u306F"enabled"\u307E\u305F\u306F"disabled"\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002\n \u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002\n\n\u3053\u306E\u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n\u6B21\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306FmacOS\u56FA\u6709\u3067\u3059:\n -XstartOnFirstThread\n main()\u30E1\u30BD\u30C3\u30C9\u3092\u6700\u521D(AppKit)\u306E\u30B9\u30EC\u30C3\u30C9\u3067\u5B9F\u884C\u3059\u308B\n -Xdock:name=\n Dock\u306B\u8868\u793A\u3055\u308C\u308B\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n -Xdock:icon=\n Dock\u306B\u8868\u793A\u3055\u308C\u308B\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n\n diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties index cdf9e09633d62117a527d1107022d0a23f0db922..35ec035c8d7d638e29f2f7eebc92adc4020678be 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -30,12 +30,12 @@ java.launcher.opt.vmselect =\ {0}\t \u9009\u62E9 "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t \u662F "{1}" VM \u7684\u540C\u4E49\u8BCD [\u5DF2\u8FC7\u65F6]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n -classpath <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n --class-path <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n \u4F7F\u7528 {0} \u5206\u9694\u7684, \u7528\u4E8E\u641C\u7D22\u7C7B\u6587\u4EF6\u7684\u76EE\u5F55, JAR \u6863\u6848\n \u548C ZIP \u6863\u6848\u5217\u8868\u3002\n -p <\u6A21\u5757\u8DEF\u5F84>\n --module-path <\u6A21\u5757\u8DEF\u5F84>...\n \u7528 {0} \u5206\u9694\u7684\u76EE\u5F55\u5217\u8868, \u6BCF\u4E2A\u76EE\u5F55\n \u90FD\u662F\u4E00\u4E2A\u5305\u542B\u6A21\u5757\u7684\u76EE\u5F55\u3002\n --upgrade-module-path <\u6A21\u5757\u8DEF\u5F84>...\n \u7528 {0} \u5206\u9694\u7684\u76EE\u5F55\u5217\u8868, \u6BCF\u4E2A\u76EE\u5F55\n \u90FD\u662F\u4E00\u4E2A\u5305\u542B\u6A21\u5757\u7684\u76EE\u5F55, \u8FD9\u4E9B\u6A21\u5757\n \u7528\u4E8E\u66FF\u6362\u8FD0\u884C\u65F6\u6620\u50CF\u4E2D\u7684\u53EF\u5347\u7EA7\u6A21\u5757\n --add-modules <\u6A21\u5757\u540D\u79F0>[,<\u6A21\u5757\u540D\u79F0>...]\n \u9664\u4E86\u521D\u59CB\u6A21\u5757\u4E4B\u5916\u8981\u89E3\u6790\u7684\u6839\u6A21\u5757\u3002\n <\u6A21\u5757\u540D\u79F0> \u8FD8\u53EF\u4EE5\u4E3A ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --list-modules\n \u5217\u51FA\u53EF\u89C2\u5BDF\u6A21\u5757\u5E76\u9000\u51FA\n -d \n --describe-module <\u6A21\u5757\u540D\u79F0>\n \u63CF\u8FF0\u6A21\u5757\u5E76\u9000\u51FA\n --dry-run \u521B\u5EFA VM \u5E76\u52A0\u8F7D\u4E3B\u7C7B, \u4F46\u4E0D\u6267\u884C main \u65B9\u6CD5\u3002\n \u6B64 --dry-run \u9009\u9879\u5BF9\u4E8E\u9A8C\u8BC1\u8BF8\u5982\n \u6A21\u5757\u7CFB\u7EDF\u914D\u7F6E\u8FD9\u6837\u7684\u547D\u4EE4\u884C\u9009\u9879\u53EF\u80FD\u975E\u5E38\u6709\u7528\u3002\n --validate-modules\n \u9A8C\u8BC1\u6240\u6709\u6A21\u5757\u5E76\u9000\u51FA\n --validate-modules \u9009\u9879\u5BF9\u4E8E\u67E5\u627E\n \u6A21\u5757\u8DEF\u5F84\u4E2D\u6A21\u5757\u7684\u51B2\u7A81\u53CA\u5176\u4ED6\u9519\u8BEF\u53EF\u80FD\u975E\u5E38\u6709\u7528\u3002\n -D<\u540D\u79F0>=<\u503C>\n \u8BBE\u7F6E\u7CFB\u7EDF\u5C5E\u6027\n -verbose:[class|module|gc|jni]\n \u4E3A\u7ED9\u5B9A\u5B50\u7CFB\u7EDF\u542F\u7528\u8BE6\u7EC6\u8F93\u51FA\n -version \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\u5E76\u9000\u51FA\n --version \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u9000\u51FA\n -showversion \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\u5E76\u7EE7\u7EED\n --show-version\n \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u7EE7\u7EED\n --show-module-resolution\n \u5728\u542F\u52A8\u8FC7\u7A0B\u4E2D\u663E\u793A\u6A21\u5757\u89E3\u6790\u8F93\u51FA\n -? -h -help\n \u5C06\u6B64\u5E2E\u52A9\u6D88\u606F\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\n --help \u5C06\u6B64\u5E2E\u52A9\u6D88\u606F\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\n -X \u5C06\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\n --help-extra \u5C06\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\n -ea[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n -enableassertions[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n \u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u542F\u7528\u65AD\u8A00\n -da[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n -disableassertions[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n \ -\u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u7981\u7528\u65AD\u8A00\n -esa | -enablesystemassertions\n \u542F\u7528\u7CFB\u7EDF\u65AD\u8A00\n -dsa | -disablesystemassertions\n \u7981\u7528\u7CFB\u7EDF\u65AD\u8A00\n -agentlib:<\u5E93\u540D>[=<\u9009\u9879>]\n \u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93 <\u5E93\u540D>, \u4F8B\u5982 -agentlib:jdwp\n \u53E6\u8BF7\u53C2\u9605 -agentlib:jdwp=help\n -agentpath:<\u8DEF\u5F84\u540D>[=<\u9009\u9879>]\n \u6309\u5B8C\u6574\u8DEF\u5F84\u540D\u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93\n -javaagent:[=<\u9009\u9879>]\n \u52A0\u8F7D Java \u7F16\u7A0B\u8BED\u8A00\u4EE3\u7406, \u8BF7\u53C2\u9605 java.lang.instrument\n -splash:<\u56FE\u50CF\u8DEF\u5F84>\n \u4F7F\u7528\u6307\u5B9A\u7684\u56FE\u50CF\u663E\u793A\u542F\u52A8\u5C4F\u5E55\n \u81EA\u52A8\u652F\u6301\u548C\u4F7F\u7528 HiDPI \u7F29\u653E\u56FE\u50CF\n (\u5982\u679C\u53EF\u7528)\u3002\u5E94\u59CB\u7EC8\u5C06\u672A\u7F29\u653E\u7684\u56FE\u50CF\u6587\u4EF6\u540D (\u4F8B\u5982, image.ext)\n \u4F5C\u4E3A\u53C2\u6570\u4F20\u9012\u7ED9 -splash \u9009\u9879\u3002\n \u5C06\u81EA\u52A8\u9009\u53D6\u63D0\u4F9B\u7684\u6700\u5408\u9002\u7684\u7F29\u653E\n \u56FE\u50CF\u3002\n \u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u53C2\u9605 SplashScreen API \u6587\u6863\n @argument \u6587\u4EF6\n \u4E00\u4E2A\u6216\u591A\u4E2A\u5305\u542B\u9009\u9879\u7684\u53C2\u6570\u6587\u4EF6\n -disable-@files\n \u963B\u6B62\u8FDB\u4E00\u6B65\u6269\u5C55\u53C2\u6570\u6587\u4EF6\n --enable-preview\n \u5141\u8BB8\u7C7B\u4F9D\u8D56\u4E8E\u6B64\u53D1\u884C\u7248\u7684\u9884\u89C8\u529F\u80FD\n\u8981\u4E3A\u957F\u9009\u9879\u6307\u5B9A\u53C2\u6570, \u53EF\u4EE5\u4F7F\u7528 --<\u540D\u79F0>=<\u503C> \u6216\n--<\u540D\u79F0> <\u503C>\u3002\n +java.launcher.opt.footer = \ -cp <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n -classpath <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n --class-path <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u7684\u7C7B\u641C\u7D22\u8DEF\u5F84>\n \u4F7F\u7528 {0} \u5206\u9694\u7684, \u7528\u4E8E\u641C\u7D22\u7C7B\u6587\u4EF6\u7684\u76EE\u5F55, JAR \u6863\u6848\n \u548C ZIP \u6863\u6848\u5217\u8868\u3002\n -p <\u6A21\u5757\u8DEF\u5F84>\n --module-path <\u6A21\u5757\u8DEF\u5F84>...\n \u7528 {0} \u5206\u9694\u7684\u76EE\u5F55\u5217\u8868, \u6BCF\u4E2A\u76EE\u5F55\n \u90FD\u662F\u4E00\u4E2A\u5305\u542B\u6A21\u5757\u7684\u76EE\u5F55\u3002\n --upgrade-module-path <\u6A21\u5757\u8DEF\u5F84>...\n \u7528 {0} \u5206\u9694\u7684\u76EE\u5F55\u5217\u8868, \u6BCF\u4E2A\u76EE\u5F55\n \u90FD\u662F\u4E00\u4E2A\u5305\u542B\u6A21\u5757\u7684\u76EE\u5F55, \u8FD9\u4E9B\u6A21\u5757\n \u7528\u4E8E\u66FF\u6362\u8FD0\u884C\u65F6\u6620\u50CF\u4E2D\u7684\u53EF\u5347\u7EA7\u6A21\u5757\n --add-modules <\u6A21\u5757\u540D\u79F0>[,<\u6A21\u5757\u540D\u79F0>...]\n \u9664\u4E86\u521D\u59CB\u6A21\u5757\u4E4B\u5916\u8981\u89E3\u6790\u7684\u6839\u6A21\u5757\u3002\n <\u6A21\u5757\u540D\u79F0> \u8FD8\u53EF\u4EE5\u4E3A ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n \u5141\u8BB8\u6267\u884C\u53D7\u9650\u672C\u673A\u64CD\u4F5C\u7684\u6A21\u5757\u3002\n \u8FD8\u53EF\u4EE5\u4E3A ALL-UNNAMED\u3002\n --list-modules\n \u5217\u51FA\u53EF\u89C2\u5BDF\u6A21\u5757\u5E76\u9000\u51FA\n -d \n --describe-module <\u6A21\u5757\u540D\u79F0>\n \u63CF\u8FF0\u6A21\u5757\u5E76\u9000\u51FA\n --dry-run \u521B\u5EFA VM \u5E76\u52A0\u8F7D\u4E3B\u7C7B, \u4F46\u4E0D\u6267\u884C main \u65B9\u6CD5\u3002\n \u6B64 --dry-run \u9009\u9879\u5BF9\u4E8E\u9A8C\u8BC1\u8BF8\u5982\n \u6A21\u5757\u7CFB\u7EDF\u914D\u7F6E\u8FD9\u6837\u7684\u547D\u4EE4\u884C\u9009\u9879\u53EF\u80FD\u975E\u5E38\u6709\u7528\u3002\n --validate-modules\n \u9A8C\u8BC1\u6240\u6709\u6A21\u5757\u5E76\u9000\u51FA\n --validate-modules \u9009\u9879\u5BF9\u4E8E\u67E5\u627E\n \u6A21\u5757\u8DEF\u5F84\u4E2D\u6A21\u5757\u7684\u51B2\u7A81\u53CA\u5176\u4ED6\u9519\u8BEF\u53EF\u80FD\u975E\u5E38\u6709\u7528\u3002\n -D<\u540D\u79F0>=<\u503C>\n \u8BBE\u7F6E\u7CFB\u7EDF\u5C5E\u6027\n -verbose:[class|module|gc|jni]\n \u4E3A\u7ED9\u5B9A\u5B50\u7CFB\u7EDF\u542F\u7528\u8BE6\u7EC6\u8F93\u51FA\n -version \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\u5E76\u9000\u51FA\n --version \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u9000\u51FA\n -showversion \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\u5E76\u7EE7\u7EED\n --show-version\n \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u7EE7\u7EED\n --show-module-resolution\n \u5728\u542F\u52A8\u8FC7\u7A0B\u4E2D\u663E\u793A\u6A21\u5757\u89E3\u6790\u8F93\u51FA\n -? -h -help\n \u5C06\u6B64\u5E2E\u52A9\u6D88\u606F\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\n --help \u5C06\u6B64\u5E2E\u52A9\u6D88\u606F\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\n -X \u5C06\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9\u8F93\u51FA\u5230\u9519\u8BEF\u6D41\n --help-extra \u5C06\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\n -ea[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n -enableassertions[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n \ +\u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u542F\u7528\u65AD\u8A00\n -da[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n -disableassertions[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n \u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u7981\u7528\u65AD\u8A00\n -esa | -enablesystemassertions\n \u542F\u7528\u7CFB\u7EDF\u65AD\u8A00\n -dsa | -disablesystemassertions\n \u7981\u7528\u7CFB\u7EDF\u65AD\u8A00\n -agentlib:<\u5E93\u540D>[=<\u9009\u9879>]\n \u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93 <\u5E93\u540D>, \u4F8B\u5982 -agentlib:jdwp\n \u53E6\u8BF7\u53C2\u9605 -agentlib:jdwp=help\n -agentpath:<\u8DEF\u5F84\u540D>[=<\u9009\u9879>]\n \u6309\u5B8C\u6574\u8DEF\u5F84\u540D\u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93\n -javaagent:[=<\u9009\u9879>]\n \u52A0\u8F7D Java \u7F16\u7A0B\u8BED\u8A00\u4EE3\u7406, \u8BF7\u53C2\u9605 java.lang.instrument\n -splash:<\u56FE\u50CF\u8DEF\u5F84>\n \u4F7F\u7528\u6307\u5B9A\u7684\u56FE\u50CF\u663E\u793A\u542F\u52A8\u5C4F\u5E55\n \u81EA\u52A8\u652F\u6301\u548C\u4F7F\u7528 HiDPI \u7F29\u653E\u56FE\u50CF\n (\u5982\u679C\u53EF\u7528)\u3002\u5E94\u59CB\u7EC8\u5C06\u672A\u7F29\u653E\u7684\u56FE\u50CF\u6587\u4EF6\u540D (\u4F8B\u5982, image.ext)\n \u4F5C\u4E3A\u53C2\u6570\u4F20\u9012\u7ED9 -splash \u9009\u9879\u3002\n \u5C06\u81EA\u52A8\u9009\u53D6\u63D0\u4F9B\u7684\u6700\u5408\u9002\u7684\u7F29\u653E\n \u56FE\u50CF\u3002\n \u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u53C2\u9605 SplashScreen API \u6587\u6863\n @argument \u6587\u4EF6\n \u4E00\u4E2A\u6216\u591A\u4E2A\u5305\u542B\u9009\u9879\u7684\u53C2\u6570\u6587\u4EF6\n -disable-@files\n \u963B\u6B62\u8FDB\u4E00\u6B65\u6269\u5C55\u53C2\u6570\u6587\u4EF6\n --enable-preview\n \u5141\u8BB8\u7C7B\u4F9D\u8D56\u4E8E\u6B64\u53D1\u884C\u7248\u7684\u9884\u89C8\u529F\u80FD\n\u8981\u4E3A\u957F\u9009\u9879\u6307\u5B9A\u53C2\u6570, \u53EF\u4EE5\u4F7F\u7528 --<\u540D\u79F0>=<\u503C> \u6216\n--<\u540D\u79F0> <\u503C>\u3002\n # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch \u7981\u7528\u540E\u53F0\u7F16\u8BD1\n -Xbootclasspath/a:<\u4EE5 {0} \u5206\u9694\u7684\u76EE\u5F55\u548C zip/jar \u6587\u4EF6>\n \u9644\u52A0\u5728\u5F15\u5BFC\u7C7B\u8DEF\u5F84\u672B\u5C3E\n -Xcheck:jni \u5BF9 JNI \u51FD\u6570\u6267\u884C\u5176\u4ED6\u68C0\u67E5\n -Xcomp \u5F3A\u5236\u5728\u9996\u6B21\u8C03\u7528\u65F6\u7F16\u8BD1\u65B9\u6CD5\n -Xdebug \u4E0D\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002\u4E3A\u5B9E\u73B0\u5411\u540E\u517C\u5BB9\u800C\u63D0\u4F9B\u3002\n -Xdiag \u663E\u793A\u9644\u52A0\u8BCA\u65AD\u6D88\u606F\n -Xfuture \u542F\u7528\u6700\u4E25\u683C\u7684\u68C0\u67E5\uFF0C\u9884\u671F\u5C06\u6765\u7684\u9ED8\u8BA4\u503C\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n -Xint \u4EC5\u89E3\u91CA\u6A21\u5F0F\u6267\u884C\n -Xinternalversion\n \u663E\u793A\u6BD4 -version \u9009\u9879\u66F4\u8BE6\u7EC6\u7684\n JVM \u7248\u672C\u4FE1\u606F\n -Xlog: \u914D\u7F6E\u6216\u542F\u7528\u91C7\u7528 Java \u865A\u62DF\n \u673A (Java Virtual Machine, JVM) \u7EDF\u4E00\u8BB0\u5F55\u6846\u67B6\u8FDB\u884C\u4E8B\u4EF6\u8BB0\u5F55\u3002\u4F7F\u7528 -Xlog:help\n \u53EF\u4E86\u89E3\u8BE6\u7EC6\u4FE1\u606F\u3002\n -Xloggc: \u5C06 GC \u72B6\u6001\u8BB0\u5F55\u5728\u6587\u4EF6\u4E2D\uFF08\u5E26\u65F6\u95F4\u6233\uFF09\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u5C06\u6765\u7684\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\u5B83\u5C06\u66FF\u6362\u4E3A -Xlog:gc:\u3002\n -Xmixed \u6DF7\u5408\u6A21\u5F0F\u6267\u884C\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xmn \u4E3A\u5E74\u8F7B\u4EE3\uFF08\u65B0\u751F\u4EE3\uFF09\u8BBE\u7F6E\u521D\u59CB\u548C\u6700\u5927\u5806\u5927\u5C0F\n \uFF08\u4EE5\u5B57\u8282\u4E3A\u5355\u4F4D\uFF09\n -Xms \u8BBE\u7F6E\u521D\u59CB Java \u5806\u5927\u5C0F\n -Xmx \u8BBE\u7F6E\u6700\u5927 Java \u5806\u5927\u5C0F\n -Xnoclassgc \u7981\u7528\u7C7B\u5783\u573E\u6536\u96C6\n -Xrs \u51CF\u5C11 Java/VM \u5BF9\u64CD\u4F5C\u7CFB\u7EDF\u4FE1\u53F7\u7684\u4F7F\u7528\uFF08\u8BF7\u53C2\u89C1\u6587\u6863\uFF09\n -Xshare:auto \u5728\u53EF\u80FD\u7684\u60C5\u51B5\u4E0B\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xshare:off \u4E0D\u5C1D\u8BD5\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\n -Xshare:on \u8981\u6C42\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF0C\u5426\u5219\u5C06\u5931\u8D25\u3002\n \u8FD9\u662F\u4E00\u4E2A\u6D4B\u8BD5\u9009\u9879\uFF0C\u53EF\u80FD\u5BFC\u81F4\u95F4\u6B47\u6027\n \u6545\u969C\u3002\u4E0D\u5E94\u5728\u751F\u4EA7\u73AF\u5883\u4E2D\u4F7F\u7528\u5B83\u3002\n -XshowSettings \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:all\n \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:locale\n \u663E\u793A\u6240\u6709\u4E0E\u533A\u57DF\u8BBE\u7F6E\u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:properties\n \u663E\u793A\u6240\u6709\u5C5E\u6027\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:vm\n \u663E\u793A\u6240\u6709\u4E0E vm \u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:system\n \uFF08\u4EC5 Linux\uFF09\u663E\u793A\u4E3B\u673A\u7CFB\u7EDF\u6216\u5BB9\u5668\n \u914D\u7F6E\u5E76\u7EE7\u7EED\n -Xss \u8BBE\u7F6E Java \u7EBF\u7A0B\u5806\u6808\u5927\u5C0F\n -Xverify \ -\u8BBE\u7F6E\u5B57\u8282\u7801\u9A8C\u8BC1\u5668\u7684\u6A21\u5F0F\n \u8BF7\u6CE8\u610F\uFF0C\u9009\u9879 -Xverify:none \u5DF2\u8FC7\u65F6\uFF0C\n \u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n --add-reads =(,)*\n \u66F4\u65B0 \u4EE5\u8BFB\u53D6 \uFF0C\u800C\u65E0\u8BBA\n \u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002 \n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u8BFB\u53D6\u6240\u6709\u672A\u547D\u540D\n \u6A21\u5757\u3002\n --add-exports /=(,)*\n \u66F4\u65B0 \u4EE5\u5C06 \u5BFC\u51FA\u5230 \uFF0C\n \u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u5BFC\u51FA\u5230\u6240\u6709\n \u672A\u547D\u540D\u6A21\u5757\u3002\n --add-opens /=(,)*\n \u66F4\u65B0 \u4EE5\u5728 \u4E2D\u6253\u5F00\n \uFF0C\u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n --illegal-access=\n \u5141\u8BB8\u6216\u62D2\u7EDD\u901A\u8FC7\u672A\u547D\u540D\u6A21\u5757\u4E2D\u7684\u4EE3\u7801\u5BF9\u547D\u540D\u6A21\u5757\u4E2D\u7684\n \u7C7B\u578B\u6210\u5458\u8FDB\u884C\u8BBF\u95EE\u3002\n \u4E3A "deny"\u3001"permit"\u3001"warn" \u6216 "debug" \u4E4B\u4E00\n \u6B64\u9009\u9879\u5C06\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n --limit-modules [,...]\n \u9650\u5236\u53EF\u89C2\u5BDF\u6A21\u5757\u7684\u9886\u57DF\n --patch-module =({0})*\n \u4F7F\u7528 JAR \u6587\u4EF6\u6216\u76EE\u5F55\u4E2D\u7684\u7C7B\u548C\u8D44\u6E90\n \u8986\u76D6\u6216\u589E\u5F3A\u6A21\u5757\u3002\n --source \n \u8BBE\u7F6E\u6E90\u6587\u4EF6\u6A21\u5F0F\u4E2D\u6E90\u7684\u7248\u672C\u3002\n\n\u8FD9\u4E9B\u989D\u5916\u9009\u9879\u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002\n +\u8BBE\u7F6E\u5B57\u8282\u7801\u9A8C\u8BC1\u5668\u7684\u6A21\u5F0F\n \u8BF7\u6CE8\u610F\uFF0C\u9009\u9879 -Xverify:none \u5DF2\u8FC7\u65F6\uFF0C\n \u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n --add-reads =(,)*\n \u66F4\u65B0 \u4EE5\u8BFB\u53D6 \uFF0C\u800C\u65E0\u8BBA\n \u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002 \n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u8BFB\u53D6\u6240\u6709\u672A\u547D\u540D\n \u6A21\u5757\u3002\n --add-exports /=(,)*\n \u66F4\u65B0 \u4EE5\u5C06 \u5BFC\u51FA\u5230 \uFF0C\n \u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u5BFC\u51FA\u5230\u6240\u6709\n \u672A\u547D\u540D\u6A21\u5757\u3002\n --add-opens /=(,)*\n \u66F4\u65B0 \u4EE5\u5728 \u4E2D\u6253\u5F00\n \uFF0C\u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n --limit-modules [,...]\n \u9650\u5236\u53EF\u89C2\u5BDF\u6A21\u5757\u7684\u9886\u57DF\n --patch-module =({0})*\n \u4F7F\u7528 JAR \u6587\u4EF6\u6216\u76EE\u5F55\u4E2D\u7684\u7C7B\u548C\u8D44\u6E90\n \u8986\u76D6\u6216\u589E\u5F3A\u6A21\u5757\u3002\n --source \n \u8BBE\u7F6E\u6E90\u6587\u4EF6\u6A21\u5F0F\u4E2D\u6E90\u7684\u7248\u672C\u3002\n --finalization=\n \u63A7\u5236 JVM \u662F\u5426\u6267\u884C\u5BF9\u8C61\u6700\u7EC8\u5904\u7406\uFF0C\n \u5176\u4E2D \u4E3A "enabled" \u6216 "disabled" \u4E4B\u4E00\u3002\n \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C\u6700\u7EC8\u5904\u7406\u5904\u4E8E\u542F\u7528\u72B6\u6001\u3002\n\n\u8FD9\u4E9B\u989D\u5916\u9009\u9879\u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n\u4EE5\u4E0B\u9009\u9879\u662F\u7279\u5B9A\u4E8E macOS \u7684\u9009\u9879\uFF1A\n -XstartOnFirstThread\n \u5728\u7B2C\u4E00\u4E2A (AppKit) \u7EBF\u7A0B\u4E0A\u8FD0\u884C main() \u65B9\u6CD5\n -Xdock:name=\n \u8986\u76D6\u505C\u9760\u680F\u4E2D\u663E\u793A\u7684\u9ED8\u8BA4\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\n -Xdock:icon=\n \u8986\u76D6\u505C\u9760\u680F\u4E2D\u663E\u793A\u7684\u9ED8\u8BA4\u56FE\u6807\n\n diff --git a/src/java.base/share/classes/sun/net/dns/ResolverConfiguration.java b/src/java.base/share/classes/sun/net/dns/ResolverConfiguration.java index e0048d80d3ebd9b257add0634ffe0c57949ba7c4..ecd2dddf35799c7d94e63886689de42b27041b44 100644 --- a/src/java.base/share/classes/sun/net/dns/ResolverConfiguration.java +++ b/src/java.base/share/classes/sun/net/dns/ResolverConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ import java.util.List; * @since 1.4 */ -public abstract class ResolverConfiguration { +public sealed abstract class ResolverConfiguration permits ResolverConfigurationImpl { private static final Object lock = new Object(); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java index 843baea872caaae2c02d8a09abef31b9faa29ebb..151a28cd4dba38fceafe8d80e368839bb27162b4 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java @@ -29,17 +29,32 @@ import java.io.*; import java.net.PasswordAuthentication; import java.net.ProtocolException; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.StandardCharsets; import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivilegedAction; +import java.security.Security; +import java.text.Normalizer; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; import java.util.Objects; import java.util.Random; +import java.util.Set; +import java.util.function.BiConsumer; import sun.net.NetProperties; import sun.net.www.HeaderParser; import sun.nio.cs.ISO_8859_1; +import sun.security.util.KnownOIDs; +import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT; @@ -57,22 +72,67 @@ class DigestAuthentication extends AuthenticationInfo { private String authMethod; - private static final String compatPropName = "http.auth.digest." + + private static final String propPrefix = "http.auth.digest."; + + private static final String compatPropName = propPrefix + "quoteParameters"; + // Takes a set and input string containing comma separated values. converts to upper + // case, and trims each value, then applies given function to set and value + // (either add or delete element from set) + private static void processPropValue(String input, + Set theSet, + BiConsumer,String> consumer) + { + if (input == null) { + return; + } + String[] values = input.toUpperCase(Locale.ROOT).split(","); + for (String v : values) { + consumer.accept(theSet, v.trim()); + } + } + + private static final String secPropName = + propPrefix + "disabledAlgorithms"; + + // A net property which overrides the disabled set above. + private static final String enabledAlgPropName = + propPrefix + "reEnabledAlgorithms"; + + // Set of disabled message digest algorithms + private static final Set disabledDigests; + // true if http.auth.digest.quoteParameters Net property is true private static final boolean delimCompatFlag; + private static final PlatformLogger logger = + HttpURLConnection.getHttpLogger(); + static { @SuppressWarnings("removal") Boolean b = AccessController.doPrivileged( - new PrivilegedAction<>() { - public Boolean run() { - return NetProperties.getBoolean(compatPropName); - } - } + (PrivilegedAction) () -> NetProperties.getBoolean(compatPropName) ); delimCompatFlag = (b == null) ? false : b.booleanValue(); + + @SuppressWarnings("removal") + String secprops = AccessController.doPrivileged( + (PrivilegedAction) () -> Security.getProperty(secPropName) + ); + + Set algs = new HashSet<>(); + + // add the default insecure algorithms to set + processPropValue(secprops, algs, (set, elem) -> set.add(elem)); + + @SuppressWarnings("removal") + String netprops = AccessController.doPrivileged( + (PrivilegedAction) () -> NetProperties.get(enabledAlgPropName) + ); + // remove any algorithms from disabled set that were opted-in by user + processPropValue(netprops, algs, (set, elem) -> set.remove(elem)); + disabledDigests = Set.copyOf(algs); } // Authentication parameters defined in RFC2617. @@ -90,9 +150,18 @@ class DigestAuthentication extends AuthenticationInfo { private String cnonce; private String nonce; private String algorithm; + // Normally same as algorithm, but excludes the -SESS suffix if present + private String digestName; + private String charset; private int NCcount=0; - // The H(A1) string used for MD5-sess + // true if the server supports user hashing + // in which case the username returned to server + // will be H(unq(username) ":" unq(realm)) + // meaning the username doesn't appear in the clear + private boolean userhash; + + // The H(A1) string used for XXX-sess private String cachedHA1; // Force the HA1 value to be recalculated because the nonce has changed @@ -112,8 +181,10 @@ class DigestAuthentication extends AuthenticationInfo { serverQop = false; opaque = null; algorithm = null; + digestName = null; cachedHA1 = null; nonce = null; + charset = null; setNewCnonce(); } @@ -151,6 +222,24 @@ class DigestAuthentication extends AuthenticationInfo { redoCachedHA1 = true; } + synchronized boolean getUserhash() { + return userhash; + } + + synchronized void setUserhash(boolean userhash) { + this.userhash = userhash; + } + + synchronized Charset getCharset() { + return "UTF-8".equals(charset) + ? StandardCharsets.UTF_8 + : StandardCharsets.ISO_8859_1; + } + + synchronized void setCharset(String charset) { + this.charset = charset; + } + synchronized void setQop (String qop) { if (qop != null) { String items[] = qop.split(","); @@ -191,7 +280,13 @@ class DigestAuthentication extends AuthenticationInfo { } synchronized String getAlgorithm () { return algorithm;} + synchronized String getDigestName () { + return digestName; + } synchronized void setAlgorithm (String s) { algorithm=s;} + synchronized void setDigestName (String s) { + this.digestName = s; + } } Parameters params; @@ -309,6 +404,16 @@ class DigestAuthentication extends AuthenticationInfo { params.setNonce (p.findValue("nonce")); params.setOpaque (p.findValue("opaque")); params.setQop (p.findValue("qop")); + params.setUserhash (Boolean.valueOf(p.findValue("userhash"))); + String charset = p.findValue("charset"); + if (charset == null) { + charset = "ISO_8859_1"; + } else if (!charset.equalsIgnoreCase("UTF-8")) { + // UTF-8 is only valid value. ISO_8859_1 represents default behavior + // when the parameter is not set. + return false; + } + params.setCharset(charset.toUpperCase(Locale.ROOT)); String uri=""; String method; @@ -333,11 +438,9 @@ class DigestAuthentication extends AuthenticationInfo { authMethod = Character.toUpperCase(authMethod.charAt(0)) + authMethod.substring(1).toLowerCase(); } - String algorithm = p.findValue("algorithm"); - if (algorithm == null || algorithm.isEmpty()) { - algorithm = "MD5"; // The default, accoriding to rfc2069 - } - params.setAlgorithm (algorithm); + + if (!setAlgorithmNames(p, params)) + return false; // If authQop is true, then the server is doing RFC2617 and // has offered qop=auth. We do not support any other modes @@ -356,6 +459,38 @@ class DigestAuthentication extends AuthenticationInfo { } } + // Algorithm name is stored in two separate fields (of Paramaeters) + // This allows for variations in digest algorithm name (aliases) + // and also allow for the -sess variant defined in HTTP Digest protocol + // returns false if algorithm not supported + private static boolean setAlgorithmNames(HeaderParser p, Parameters params) { + String algorithm = p.findValue("algorithm"); + String digestName = algorithm; + if (algorithm == null || algorithm.isEmpty()) { + algorithm = "MD5"; // The default, accoriding to rfc2069 + digestName = "MD5"; + } else { + algorithm = algorithm.toUpperCase(Locale.ROOT); + digestName = algorithm; + } + if (algorithm.endsWith("-SESS")) { + digestName = algorithm.substring(0, algorithm.length() - 5); + algorithm = digestName + "-sess"; // suffix lower case + } + if (digestName.equals("SHA-512-256")) { + digestName = "SHA-512/256"; + } + var oid = KnownOIDs.findMatch(digestName); + if (oid == null) { + log("unknown algorithm: " + algorithm); + return false; + } + digestName = oid.stdName(); + params.setAlgorithm (algorithm); + params.setDigestName (digestName); + return true; + } + /* Calculate the Authorization header field given the request URI * and based on the authorization information in params */ @@ -367,6 +502,14 @@ class DigestAuthentication extends AuthenticationInfo { String cnonce = params.getCnonce (); String nonce = params.getNonce (); String algorithm = params.getAlgorithm (); + String digest = params.getDigestName (); + try { + validateDigest(digest); + } catch (IOException e) { + return null; + } + Charset charset = params.getCharset(); + boolean userhash = params.getUserhash (); params.incrementNC (); int nccount = params.getNCCount (); String ncstring=null; @@ -378,10 +521,14 @@ class DigestAuthentication extends AuthenticationInfo { ncstring = zeroPad [len] + ncstring; } + boolean session = algorithm.endsWith ("-sess"); + try { response = computeDigest(true, pw.getUserName(),passwd,realm, - method, uri, nonce, cnonce, ncstring); - } catch (NoSuchAlgorithmException ex) { + method, uri, nonce, cnonce, ncstring, + digest, session, charset); + } catch (CharacterCodingException | NoSuchAlgorithmException ex) { + log(ex.getMessage()); return null; } @@ -402,11 +549,24 @@ class DigestAuthentication extends AuthenticationInfo { qopS = ", qop=auth"; } + String user = pw.getUserName(); + String userhashField = ""; + try { + if (userhash) { + user = computeUserhash(digest, user, realm, charset); + userhashField = ", userhash=true"; + } + } catch (CharacterCodingException | NoSuchAlgorithmException ex) { + log(ex.getMessage()); + return null; + } + String value = authMethod - + " username=\"" + pw.getUserName() + + " username=\"" + user + "\", realm=\"" + realm + "\", nonce=\"" + nonce + ncfield + + userhashField + ", uri=\"" + uri + "\", response=\"" + response + "\"" + algoS; @@ -427,6 +587,27 @@ class DigestAuthentication extends AuthenticationInfo { checkResponse (header, method, url.getFile()); } + private static void log(String msg) { + if (logger.isLoggable(PlatformLogger.Level.INFO)) { + logger.info(msg); + } + } + + private void validateDigest(String name) throws IOException { + if (getAuthType() == AuthCacheValue.Type.Server && + getProtocolScheme().equals("https")) { + // HTTPS server authentication can use any algorithm + return; + } + if (disabledDigests.contains(name)) { + String msg = "Rejecting digest authentication with insecure algorithm: " + + name; + log(msg + " This constraint may be relaxed by setting " + + "the \"http.auth.digest.reEnabledAlgorithms\" system property."); + throw new IOException(msg); + } + } + public void checkResponse (String header, String method, String uri) throws IOException { char[] passwd = pw.getPassword(); @@ -436,6 +617,9 @@ class DigestAuthentication extends AuthenticationInfo { String cnonce = params.cnonce; String nonce = params.getNonce (); String algorithm = params.getAlgorithm (); + String digest = params.getDigestName (); + Charset charset = params.getCharset(); + validateDigest(digest); int nccount = params.getNCCount (); String ncstring=null; @@ -443,15 +627,21 @@ class DigestAuthentication extends AuthenticationInfo { throw new ProtocolException ("No authentication information in response"); } + boolean session = algorithm.endsWith ("-SESS"); + if (session) { + algorithm = algorithm.substring(0, algorithm.length() - 5); + } + if (nccount != -1) { - ncstring = Integer.toHexString (nccount).toUpperCase(); + ncstring = Integer.toHexString (nccount).toUpperCase(Locale.ROOT); int len = ncstring.length(); if (len < 8) ncstring = zeroPad [len] + ncstring; } try { - String expected = computeDigest(false, username,passwd,realm, - method, uri, nonce, cnonce, ncstring); + String expected = computeDigest(false, username,passwd,realm, method, uri, + nonce, cnonce, ncstring, digest, + session, charset); HeaderParser p = new HeaderParser (header); String rspauth = p.findValue ("rspauth"); if (rspauth == null) { @@ -468,34 +658,45 @@ class DigestAuthentication extends AuthenticationInfo { } catch (NoSuchAlgorithmException ex) { throw new ProtocolException ("Unsupported algorithm in response"); + } catch (CharacterCodingException ex) { + throw new ProtocolException ("Invalid characters in username or password"); } } + private String computeUserhash(String digest, String user, + String realm, Charset charset) + throws NoSuchAlgorithmException, CharacterCodingException + { + MessageDigest md = MessageDigest.getInstance(digest); + String s = user + ":" + realm; + return encode(s, null, md, charset); + } + private String computeDigest( boolean isRequest, String userName, char[] password, String realm, String connMethod, String requestURI, String nonceString, - String cnonce, String ncValue - ) throws NoSuchAlgorithmException + String cnonce, String ncValue, + String algorithm, boolean session, + Charset charset + ) throws NoSuchAlgorithmException, CharacterCodingException { String A1, HashA1; - String algorithm = params.getAlgorithm (); - boolean md5sess = algorithm.equalsIgnoreCase ("MD5-sess"); - MessageDigest md = MessageDigest.getInstance(md5sess?"MD5":algorithm); + MessageDigest md = MessageDigest.getInstance(algorithm); - if (md5sess) { + if (session) { if ((HashA1 = params.getCachedHA1 ()) == null) { String s = userName + ":" + realm + ":"; - String s1 = encode (s, password, md); + String s1 = encode (s, password, md, charset); A1 = s1 + ":" + nonceString + ":" + cnonce; - HashA1 = encode(A1, null, md); + HashA1 = encode(A1, null, md, charset); params.setCachedHA1 (HashA1); } } else { A1 = userName + ":" + realm + ":"; - HashA1 = encode(A1, password, md); + HashA1 = encode(A1, password, md, charset); } String A2; @@ -504,7 +705,7 @@ class DigestAuthentication extends AuthenticationInfo { } else { A2 = ":" + requestURI; } - String HashA2 = encode(A2, null, md); + String HashA2 = encode(A2, null, md, ISO_8859_1.INSTANCE); String combo, finalHash; if (params.authQop()) { /* RRC2617 when qop=auth */ @@ -516,7 +717,7 @@ class DigestAuthentication extends AuthenticationInfo { nonceString + ":" + HashA2; } - finalHash = encode(combo, null, md); + finalHash = encode(combo, null, md, ISO_8859_1.INSTANCE); return finalHash; } @@ -530,17 +731,28 @@ class DigestAuthentication extends AuthenticationInfo { "00000000", "0000000", "000000", "00000", "0000", "000", "00", "0" }; - private String encode(String src, char[] passwd, MessageDigest md) { - md.update(src.getBytes(ISO_8859_1.INSTANCE)); + private String encode(String src, char[] passwd, MessageDigest md, Charset charset) + throws CharacterCodingException + { + boolean isUtf8 = charset.equals(StandardCharsets.UTF_8); + + if (isUtf8) { + src = Normalizer.normalize(src, Normalizer.Form.NFC); + } + md.update(src.getBytes(charset)); if (passwd != null) { - byte[] passwdBytes = new byte[passwd.length]; - for (int i=0; i>> 4) & 0xf); @@ -550,4 +762,15 @@ class DigestAuthentication extends AuthenticationInfo { } return res.toString(); } + + private static byte[] getUtf8Bytes(char[] passwd) throws CharacterCodingException { + CharBuffer cb = CharBuffer.wrap(passwd); + CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder(); + ByteBuffer bb = encoder.encode(cb); + byte[] buf = new byte[bb.remaining()]; + bb.get(buf); + if (bb.hasArray()) + Arrays.fill(bb.array(), bb.arrayOffset(), bb.capacity(), (byte)0); + return buf; + } } 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/fs/Reflect.java b/src/java.base/share/classes/sun/nio/fs/Reflect.java deleted file mode 100644 index 1f995543b6490b2f867b6deb4bed9aea21a9a4b4..0000000000000000000000000000000000000000 --- a/src/java.base/share/classes/sun/nio/fs/Reflect.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2008, 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 sun.nio.fs; - -import java.lang.reflect.*; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * Utility class for reflection. - */ - -class Reflect { - private Reflect() {} - - @SuppressWarnings("removal") - private static void setAccessible(final AccessibleObject ao) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - ao.setAccessible(true); - return null; - }}); - } - - /** - * Lookup the field of a given class. - */ - static Field lookupField(String className, String fieldName) { - try { - Class cl = Class.forName(className); - Field f = cl.getDeclaredField(fieldName); - setAccessible(f); - return f; - } catch (ClassNotFoundException x) { - throw new AssertionError(x); - } catch (NoSuchFieldException x) { - throw new AssertionError(x); - } - } -} 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 3484bd04c32d3bfc4bde87ff94c7e3326f8bbb3e..da6d1687a6d5426ffd5b6873471f59beccb3944c 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java @@ -940,7 +940,7 @@ public class PKCS7 { /** * Examine the certificate for a Subject Information Access extension - * (RFC 5280). + * (RFC 5280). * The extension's {@code accessMethod} field should contain the object * identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its * {@code accessLocation} field should contain an HTTP or HTTPS URL. 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/rsa/PSSParameters.java b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java index 5a1584b0a9ea1244820d800597329c995cf5663c..1a317a3ed146d3e9cd7707ebfe5eb1306fbcf4eb 100644 --- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java +++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java @@ -34,7 +34,6 @@ import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; -import static java.security.spec.PSSParameterSpec.DEFAULT; /** * This class implements the PSS parameters used with the RSA @@ -81,12 +80,12 @@ public final class PSSParameters extends AlgorithmParametersSpi { @Override protected void engineInit(byte[] encoded) throws IOException { - // first initialize with the DEFAULT values before - // retrieving from the encoding bytes - String mdName = DEFAULT.getDigestAlgorithm(); - MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters(); - int saltLength = DEFAULT.getSaltLength(); - int trailerField = DEFAULT.getTrailerField(); + // first initialize with the ASN.1 DEFAULT values defined in PKCS #1 + // v2.2 since the encoding bytes may not define all fields + String mdName = "SHA-1"; + MGF1ParameterSpec mgfSpec = MGF1ParameterSpec.SHA1; + int saltLength = 20; + int trailerField = PSSParameterSpec.TRAILER_FIELD_BC; DerInputStream der = new DerInputStream(encoded); DerValue[] datum = der.getSequence(4); 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/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..990b91268324688d525e80c362bee1d74b5694be 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 @@ -48,7 +48,7 @@ import javax.net.ssl.SSLProtocolException; import javax.net.ssl.SSLSession; /** - * Implementation of an non-blocking SSLEngine. + * Implementation of a non-blocking SSLEngine. * * @author Brad Wetmore */ @@ -270,7 +270,7 @@ final class SSLEngineImpl extends SSLEngine implements SSLTransport { if (ciphertext == null && !conContext.isNegotiated && conContext.isInboundClosed() && hsStatus == HandshakeStatus.NEED_WRAP) { - // Even the outboud is open, no futher data could be wrapped as: + // Even the outbound is open, no further data could be wrapped as: // 1. the outbound is empty // 2. no negotiated connection // 3. the inbound has closed, cannot complete the handshake @@ -789,17 +789,17 @@ final class SSLEngineImpl extends SSLEngine implements SSLTransport { // Is it ready to close inbound? // // No exception if the initial handshake is not started. - if (!conContext.isInputCloseNotified && - (conContext.isNegotiated || - conContext.handshakeContext != null)) { - - throw conContext.fatal(Alert.INTERNAL_ERROR, + if (!conContext.isInputCloseNotified && (conContext.isNegotiated + || conContext.handshakeContext != null)) { + throw new SSLException( "closing inbound before receiving peer's close_notify"); } - - conContext.closeInbound(); } finally { - engineLock.unlock(); + try { + conContext.closeInbound(); + } finally { + engineLock.unlock(); + } } } @@ -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..879d3901e31ff009abc25bc5391519fd10a39901 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 @@ -838,9 +838,10 @@ public final class SSLSocketImpl // No need to throw exception if the initial handshake is not started. try { if (checkCloseNotify && !conContext.isInputCloseNotified && - (conContext.isNegotiated || conContext.handshakeContext != null)) { - throw new SSLException( - "closing inbound before receiving peer's close_notify"); + (conContext.isNegotiated || + conContext.handshakeContext != null)) { + throw new SSLException( + "closing inbound before receiving peer's close_notify"); } } finally { conContext.closeInbound(); @@ -1709,19 +1710,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 032fcd768ea0900d5b3a710edf79cc75402afc76..0a1b889db6d4f97198002ad68d8f18112af0c89c 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; @@ -1919,6 +1917,8 @@ public final class Main { keysize = SecurityProviderConstants.DEF_EC_KEY_SIZE; } else if ("RSA".equalsIgnoreCase(keyAlgName)) { keysize = SecurityProviderConstants.DEF_RSA_KEY_SIZE; + } else if ("RSASSA-PSS".equalsIgnoreCase(keyAlgName)) { + keysize = SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE; } else if ("DSA".equalsIgnoreCase(keyAlgName)) { keysize = SecurityProviderConstants.DEF_DSA_KEY_SIZE; } else if ("EdDSA".equalsIgnoreCase(keyAlgName)) { @@ -2018,7 +2018,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, @@ -2029,7 +2029,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}; @@ -3560,24 +3560,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) { @@ -4946,13 +4932,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)))); } } } @@ -4973,12 +4959,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/tools/keytool/Resources_de.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java index 24cdbabc3a8b8fbdbfc3f768eb2cb24c1e5321a3..5479bc1df2d15ebb9f85ff472e8dc9036935422a 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -45,15 +45,15 @@ public class Resources_de extends java.util.ListResourceBundle { {"option.1.set.twice", "Die Option %s wurde mehrmals angegeben. Alle Angaben bis auf die letzte werden ignoriert."}, {"multiple.commands.1.2", "Nur ein Befehl ist zul\u00E4ssig: Sowohl %1$s als auch %2$s wurden angegeben."}, {"Use.keytool.help.for.all.available.commands", - "\"keytool -help\" f\u00FCr alle verf\u00FCgbaren Befehle verwenden"}, + "Verwenden Sie \"keytool -?, -h, or --help\" f\u00FCr diese Hilfemeldung"}, {"Key.and.Certificate.Management.Tool", "Schl\u00FCssel- und Zertifikatsverwaltungstool"}, {"Commands.", "Befehle:"}, {"Use.keytool.command.name.help.for.usage.of.command.name", - "Verwenden Sie \"keytool -command_name -help\" f\u00FCr die Verwendung von command_name.\nVerwenden Sie die Option -conf , um eine vorkonfigurierte Optionsdatei anzugeben."}, + "Verwenden Sie \"keytool -command_name --help\" f\u00FCr die Verwendung von command_name.\nVerwenden Sie die Option -conf , um eine vorkonfigurierte Optionsdatei anzugeben."}, // keytool: help: commands {"Generates.a.certificate.request", - "Generiert eine Zertifikatanforderung"}, //-certreq + "Generiert eine Zertifikatsanforderung"}, //-certreq {"Changes.an.entry.s.alias", "\u00C4ndert den Alias eines Eintrags"}, //-changealias {"Deletes.an.entry", @@ -65,7 +65,7 @@ public class Resources_de extends java.util.ListResourceBundle { {"Generates.a.secret.key", "Generiert einen Secret Key"}, //-genseckey {"Generates.certificate.from.a.certificate.request", - "Generiert ein Zertifikat aus einer Zertifikatanforderung"}, //-gencert + "Generiert ein Zertifikat aus einer Zertifikatsanforderung"}, //-gencert {"Generates.CRL", "Generiert eine CRL"}, //-gencrl {"Generated.keyAlgName.secret.key", "{0} Secret Key generiert"}, //-genseckey @@ -88,20 +88,25 @@ public class Resources_de extends java.util.ListResourceBundle { {"Prints.the.content.of.a.certificate", "Druckt den Content eines Zertifikats"}, //-printcert {"Prints.the.content.of.a.certificate.request", - "Druckt den Content einer Zertifikatanforderung"}, //-printcertreq + "Druckt den Content einer Zertifikatsanforderung"}, //-printcertreq {"Prints.the.content.of.a.CRL.file", "Druckt den Content einer CRL-Datei"}, //-printcrl {"Generates.a.self.signed.certificate", "Generiert ein selbst signiertes Zertifikat"}, //-selfcert {"Changes.the.store.password.of.a.keystore", "\u00C4ndert das Speicherkennwort eines Keystores"}, //-storepasswd + {"showinfo.command.help", "Zeigt sicherheitsbezogene Informationen an"}, + {"Prints.the.program.version", "Gibt die Programmversion aus"}, + // keytool: help: options {"alias.name.of.the.entry.to.process", "Aliasname des zu verarbeitenden Eintrags"}, //-alias + {"groupname.option.help", + "Gruppenname. Beispiel: der Name der elliptischen Kurve."}, //-groupname {"destination.alias", "Zielalias"}, //-destalias {"destination.key.password", - "Zielschl\u00FCssel-Kennwort"}, //-destkeypass + "Zielschl\u00FCsselkennwort"}, //-destkeypass {"destination.keystore.name", "Ziel-Keystore-Name"}, //-destkeystore {"destination.keystore.password.protected", @@ -138,6 +143,7 @@ public class Resources_de extends java.util.ListResourceBundle { "Kein Prompt"}, //-noprompt {"password.through.protected.mechanism", "Kennwort \u00FCber gesch\u00FCtzten Mechanismus"}, //-protected + {"tls.option.help", "Zeigt TLS-Konfigurationsinformationen an"}, // The following 2 values should span 2 lines, the first for the // option itself, the second for its -providerArg value. @@ -154,10 +160,14 @@ public class Resources_de extends java.util.ListResourceBundle { "Ausgabe in RFC-Stil"}, //-rfc {"signature.algorithm.name", "Signaturalgorithmusname"}, //-sigalg + {"signer.alias", + "Signaturgeberalias"}, //-signer + {"signer.key.password", + "Signaturgeber-Schl\u00FCsselkennwort"}, //-signerkeypass {"source.alias", "Quellalias"}, //-srcalias {"source.key.password", - "Quellschl\u00FCssel-Kennwort"}, //-srckeypass + "Quellschl\u00FCsselkennwort"}, //-srckeypass {"source.keystore.name", "Quell-Keystore-Name"}, //-srckeystore {"source.keystore.password.protected", @@ -173,7 +183,7 @@ public class Resources_de extends java.util.ListResourceBundle { {"signed.jar.file", "Signierte JAR-Datei"}, //=jarfile {"certificate.validity.start.date.time", - "Anfangsdatum/-zeit f\u00FCr Zertifikatsg\u00FCltigkeit"}, //-startdate + "Startdatum/-zeit f\u00FCr Zertifikatsg\u00FCltigkeit"}, //-startdate {"keystore.password", "Keystore-Kennwort"}, //-storepass {"keystore.type", @@ -188,8 +198,8 @@ public class Resources_de extends java.util.ListResourceBundle { "Serielle ID des zu entziehenden Certs"}, //-id // keytool: Running part {"keytool.error.", "Keytool-Fehler: "}, - {"Illegal.option.", "Ung\u00FCltige Option: "}, - {"Illegal.value.", "Ung\u00FCltiger Wert: "}, + {"Illegal.option.", "Unzul\u00E4ssige Option: "}, + {"Illegal.value.", "Unzul\u00E4ssiger Wert: "}, {"Unknown.password.type.", "Unbekannter Kennworttyp: "}, {"Cannot.find.environment.variable.", "Umgebungsvariable kann nicht gefunden werden: "}, @@ -217,7 +227,7 @@ public class Resources_de extends java.util.ListResourceBundle { "Wenn der Keystore nicht kennwortgesch\u00FCtzt ist, d\u00FCrfen -storepass, -keypass und -new nicht angegeben werden"}, {"if.source.keystore.is.not.password.protected.then.srcstorepass.and.srckeypass.must.not.be.specified", "Wenn der Quell-Keystore nicht kennwortgesch\u00FCtzt ist, d\u00FCrfen -srcstorepass und -srckeypass nicht angegeben werden"}, - {"Illegal.startdate.value", "Ung\u00FCltiger Wert f\u00FCr Anfangsdatum"}, + {"Illegal.startdate.value", "Unzul\u00E4ssiger Wert f\u00FCr Startdatum"}, {"Validity.must.be.greater.than.zero", "G\u00FCltigkeit muss gr\u00F6\u00DFer als null sein"}, {"provclass.not.a.provider", "%s kein Provider"}, @@ -248,7 +258,6 @@ public class Resources_de extends java.util.ListResourceBundle { {"Keystore.password.is.too.short.must.be.at.least.6.characters", "Keystore-Kennwort ist zu kurz. Es muss mindestens sechs Zeichen lang sein"}, {"Unknown.Entry.Type", "Unbekannter Eintragstyp"}, - {"Too.many.failures.Alias.not.changed", "Zu viele Fehler. Alias nicht ge\u00E4ndert"}, {"Entry.for.alias.alias.successfully.imported.", "Eintrag f\u00FCr Alias {0} erfolgreich importiert."}, {"Entry.for.alias.alias.not.imported.", "Eintrag f\u00FCr Alias {0} nicht importiert."}, @@ -271,9 +280,9 @@ public class Resources_de extends java.util.ListResourceBundle { {"Certificate.stored.in.file.filename.", "Zertifikat in Datei <{0}> gespeichert"}, {"Certificate.reply.was.installed.in.keystore", - "Zertifikatantwort wurde in Keystore installiert"}, + "Zertifikatsantwort wurde in Keystore installiert"}, {"Certificate.reply.was.not.installed.in.keystore", - "Zertifikatantwort wurde nicht in Keystore installiert"}, + "Zertifikatsantwort wurde nicht in Keystore installiert"}, {"Certificate.was.added.to.keystore", "Zertifikat wurde Keystore hinzugef\u00FCgt"}, {"Certificate.was.not.added.to.keystore", @@ -287,10 +296,16 @@ public class Resources_de extends java.util.ListResourceBundle { "Alias <{0}> ist nicht vorhanden"}, {"Alias.alias.has.no.certificate", "Alias <{0}> hat kein Zertifikat"}, + {"groupname.keysize.coexist", + "Es k\u00F6nnen nicht sowohl -groupname als auch -keysize angegeben werden"}, + {"deprecate.keysize.for.ec", + "Das Angeben von -keysize zum Generieren von EC-Schl\u00FCsseln ist veraltet. Verwenden Sie stattdessen \"-groupname %s\"."}, {"Key.pair.not.generated.alias.alias.already.exists", "Schl\u00FCsselpaar wurde nicht generiert. Alias <{0}> ist bereits vorhanden"}, {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for", "Generieren von Schl\u00FCsselpaar (Typ {1}, {0} Bit) und selbst signiertem Zertifikat ({2}) mit einer G\u00FCltigkeit von {3} Tagen\n\tf\u00FCr: {4}"}, + {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for", + "Generieren von Schl\u00FCsselpaar (Typ {1}, {0} Bit) und Zertifikat ({2}), ausgestellt von <{3}>, mit einer G\u00FCltigkeit von {4} Tagen\n\tf\u00FCr: {5}"}, {"Enter.key.password.for.alias.", "Schl\u00FCsselkennwort f\u00FCr <{0}> eingeben"}, {".RETURN.if.same.as.keystore.password.", "\t(RETURN, wenn identisch mit Keystore-Kennwort): "}, @@ -303,12 +318,8 @@ public class Resources_de extends java.util.ListResourceBundle { {"Password.is.too.short.must.be.at.least.6.characters", "Kennwort ist zu kurz. Es muss mindestens sechs Zeichen lang sein"}, {"Too.many.failures.Key.entry.not.cloned", - "Zu viele Fehler. Schl\u00FCsseleintrag wurde nicht geclont"}, + "Zu viele Fehler. Schl\u00FCsseleintrag wurde nicht geklont"}, {"key.password.for.alias.", "Schl\u00FCsselkennwort f\u00FCr <{0}>"}, - {"Keystore.entry.for.id.getName.already.exists", - "Keystore-Eintrag f\u00FCr <{0}> bereits vorhanden"}, - {"Creating.keystore.entry.for.id.getName.", - "Keystore-Eintrag f\u00FCr <{0}> wird erstellt..."}, {"No.entries.from.identity.database.added", "Keine Eintr\u00E4ge aus Identity-Datenbank hinzugef\u00FCgt"}, {"Alias.name.alias", "Aliasname: {0}"}, @@ -346,7 +357,6 @@ public class Resources_de extends java.util.ListResourceBundle { {"Do.you.still.want.to.add.it.to.your.own.keystore.no.", "M\u00F6chten Sie es trotzdem zu Ihrem eigenen Keystore hinzuf\u00FCgen? [Nein]: "}, {"Trust.this.certificate.no.", "Diesem Zertifikat vertrauen? [Nein]: "}, - {"YES", "JA"}, {"New.prompt.", "Neues {0}: "}, {"Passwords.must.differ", "Kennw\u00F6rter m\u00FCssen sich unterscheiden"}, {"Re.enter.new.prompt.", "Neues {0} erneut eingeben: "}, @@ -379,15 +389,14 @@ public class Resources_de extends java.util.ListResourceBundle { {"Alias.alias.has.no.key", "Alias <{0}> verf\u00FCgt \u00FCber keinen Schl\u00FCssel"}, {"Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key", - "Alias <{0}> verweist auf einen Eintragstyp, der kein Private Key-Eintrag ist. Der Befehl -keyclone unterst\u00FCtzt nur das Klonen von Private Key-Eintr\u00E4gen"}, + "Alias <{0}> verweist auf einen Eintragstyp, der kein Private-Key-Eintrag ist. Der Befehl -keyclone unterst\u00FCtzt nur das Klonen von Private-Key-Eintr\u00E4gen"}, {".WARNING.WARNING.WARNING.", "***************** WARNING WARNING WARNING *****************"}, {"Signer.d.", "Signaturgeber #%d:"}, + {"Certificate.d.", "Zertifikat #%d:"}, {"Timestamp.", "Zeitstempel:"}, - {"Signature.", "Signatur:"}, - {"CRLs.", "CRLs:"}, - {"Certificate.owner.", "Zertifikateigent\u00FCmer: "}, + {"Certificate.owner.", "Zertifikatseigent\u00FCmer: "}, {"Not.a.signed.jar.file", "Keine signierte JAR-Datei"}, {"No.certificate.from.the.SSL.server", "Kein Zertifikat vom SSL-Server"}, @@ -398,20 +407,17 @@ public class Resources_de extends java.util.ListResourceBundle { "* Die Integrit\u00E4t der Informationen, die in Ihrem Srckeystore gespeichert sind, *\n* wurde NICHT gepr\u00FCft. Um die Integrit\u00E4t zu pr\u00FCfen, *\n* m\u00FCssen Sie Ihr Srckeystore-Kennwort angeben. *"}, {"Certificate.reply.does.not.contain.public.key.for.alias.", - "Zertifikatantwort enth\u00E4lt keinen Public Key f\u00FCr <{0}>"}, + "Zertifikatsantwort enth\u00E4lt keinen Public Key f\u00FCr <{0}>"}, {"Incomplete.certificate.chain.in.reply", "Unvollst\u00E4ndige Zertifikatskette in Antwort"}, - {"Certificate.chain.in.reply.does.not.verify.", - "Zertifikatskette in Antwort verifiziert nicht: "}, {"Top.level.certificate.in.reply.", "Zertifikat der obersten Ebene in Antwort:\n"}, {".is.not.trusted.", "... ist nicht vertrauensw\u00FCrdig. "}, {"Install.reply.anyway.no.", "Antwort trotzdem installieren? [Nein]: "}, - {"NO", "NEIN"}, {"Public.keys.in.reply.and.keystore.don.t.match", "Public Keys in Antwort und Keystore stimmen nicht \u00FCberein"}, {"Certificate.reply.and.certificate.in.keystore.are.identical", - "Zertifikatantwort und Zertifikat in Keystore sind identisch"}, + "Zertifikatsantwort und Zertifikat in Keystore sind identisch"}, {"Failed.to.establish.chain.from.reply", "Kette konnte der Antwort nicht entnommen werden"}, {"n", "N"}, @@ -419,10 +425,12 @@ public class Resources_de extends java.util.ListResourceBundle { {"Secret.key.not.generated.alias.alias.already.exists", "Secret Key wurde nicht generiert. Alias <{0}> ist bereits vorhanden"}, {"Please.provide.keysize.for.secret.key.generation", - "Geben Sie -keysize zum Erstellen eines Secret Keys an"}, + "Geben Sie -keysize zum Erstellen eines Secret Key an"}, {"warning.not.verified.make.sure.keystore.is.correct", "WARNUNG: Nicht gepr\u00FCft. Stellen Sie sicher, dass -keystore korrekt ist."}, + {"warning.not.verified.make.sure.keystore.is.correct.or.specify.trustcacerts", + "Warnung: Nicht gepr\u00FCft. Stellen Sie sicher, dass -keystore korrekt ist, oder geben Sie -trustcacerts an."}, {"Extensions.", "Erweiterungen: "}, {".Empty.value.", "(Leerer Wert)"}, @@ -439,34 +447,43 @@ public class Resources_de extends java.util.ListResourceBundle { // 8171319: keytool should print out warnings when reading or // generating cert/cert req using weak algorithms - {"the.certificate.request", "Die Zertifikatanforderung"}, + {"the.certificate.request", "Die Zertifikatsanforderung"}, {"the.issuer", "Der Aussteller"}, {"the.generated.certificate", "Das generierte Zertifikat"}, {"the.generated.crl", "Die generierte CRL"}, - {"the.generated.certificate.request", "Die generierte Zertifikatanforderung"}, + {"the.generated.certificate.request", "Die generierte Zertifikatsanforderung"}, {"the.certificate", "Das Zertifikat"}, {"the.crl", "Die CRL"}, {"the.tsa.certificate", "Das TSA-Zertifikat"}, {"the.input", "Die Eingabe"}, {"reply", "Antwort"}, {"one.in.many", "%1$s #%2$d von %3$d"}, + {"one.in.many1", "%1$s #%2$d"}, + {"one.in.many2", "%1$s von Signaturgeber #%2$d"}, + {"one.in.many3", "%1$s #%2$d von Signaturgeber #%3$d"}, {"alias.in.cacerts", "Aussteller <%s> in cacerts"}, {"alias.in.keystore", "Aussteller <%s>"}, {"with.weak", "%s (schwach)"}, + {"with.disabled", "%s (deaktiviert)"}, {"key.bit", "%1$d-Bit-%2$s-Schl\u00FCssel"}, {"key.bit.weak", "%1$d-Bit-%2$s-Schl\u00FCssel (schwach)"}, - {"unknown.size.1", "unbekannte Gr\u00F6\u00DFe: %s-Schl\u00FCssel"}, + {"key.bit.disabled", "%1$d-Bit-%2$s-Schl\u00FCssel (deaktiviert)"}, + {"unknown.size.1", "%s-Schl\u00FCssel mit unbekannter Gr\u00F6\u00DFe"}, {".PATTERN.printX509Cert.with.weak", - "Eigent\u00FCmer: {0}\nAussteller: {1}\nSeriennummer: {2}\nG\u00FCltig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic Key-Algorithmus von Subject: {8}\nVersion: {9}"}, + "Eigent\u00FCmer: {0}\nAussteller: {1}\nSeriennummer: {2}\nG\u00FCltig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic-Key-Algorithmus von Subject: {8}\nVersion: {9}"}, {"PKCS.10.with.weak", - "PKCS #10-Zertifikatanforderung (Version 1.0)\nSubject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignaturalgorithmus: %4$s\n"}, + "PKCS #10-Zertifikatsanforderung (Version 1.0)\nSubject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignaturalgorithmus: %4$s\n"}, {"verified.by.s.in.s.weak", "Von %1$s in %2$s mit %3$s verifiziert"}, - {"whose.sigalg.risk", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko."}, - {"whose.key.risk", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko."}, + {"whose.sigalg.disabled", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert."}, + {"whose.sigalg.weak", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"whose.key.disabled", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert."}, + {"whose.key.weak", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Diese Schl\u00FCsselgr\u00F6\u00DFe wird in einem zuk\u00FCnftigen Update deaktiviert."}, {"jks.storetype.warning", "Der %1$s-Keystore verwendet ein propriet\u00E4res Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\" ist."}, {"migrate.keystore.warning", "\"%1$s\" zu %4$s migriert. Der %2$s-Keystore wurde als \"%3$s\" gesichert."}, {"backup.keystore.warning", "Der urspr\u00FCngliche Keystore \"%1$s\" wird als \"%3$s\" gesichert..."}, {"importing.keystore.status", "Keystore %1$s wird in %2$s importiert..."}, + {"keyalg.option.missing.error", "Die Option -keyalg muss angegeben werden."}, + {"showinfo.no.option", "Fehlende Option f\u00FCr -showinfo. Verwenden Sie keytool -showinfo -tls."}, }; diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java index 49980f3c480f5bb986328369d11b974f14b6ef5e..43acdf4f2d33d1de4526660d8a5eb0df271777b8 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -96,6 +96,7 @@ public class Resources_ja extends java.util.ListResourceBundle { {"Changes.the.store.password.of.a.keystore", "\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30B9\u30C8\u30A2\u30FB\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5909\u66F4\u3057\u307E\u3059"}, //-storepasswd {"showinfo.command.help", "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u95A2\u9023\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059"}, + {"Prints.the.program.version", "\u30D7\u30ED\u30B0\u30E9\u30E0\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059"}, // keytool: help: options {"alias.name.of.the.entry.to.process", @@ -159,6 +160,10 @@ public class Resources_ja extends java.util.ListResourceBundle { "RFC\u30B9\u30BF\u30A4\u30EB\u306E\u51FA\u529B"}, //-rfc {"signature.algorithm.name", "\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u540D"}, //-sigalg + {"signer.alias", + "\u7F72\u540D\u8005\u306E\u5225\u540D"}, //-signer + {"signer.key.password", + "\u7F72\u540D\u8005\u306E\u30AD\u30FC\u306E\u30D1\u30B9\u30EF\u30FC\u30C9"}, //-signerkeypass {"source.alias", "\u30BD\u30FC\u30B9\u5225\u540D"}, //-srcalias {"source.key.password", @@ -299,6 +304,8 @@ public class Resources_ja extends java.util.ListResourceBundle { "\u30AD\u30FC\u30FB\u30DA\u30A2\u306F\u751F\u6210\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u5225\u540D<{0}>\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059"}, {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for", "{3}\u65E5\u9593\u6709\u52B9\u306A{0}\u30D3\u30C3\u30C8\u306E{1}\u306E\u30AD\u30FC\u30FB\u30DA\u30A2\u3068\u81EA\u5DF1\u7F72\u540D\u578B\u8A3C\u660E\u66F8({2})\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u540D: {4}"}, + {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for", + "{4}\u65E5\u9593\u6709\u52B9\u306A{0}\u30D3\u30C3\u30C8\u306E{1}\u30AD\u30FC\u30FB\u30DA\u30A2\u3068<{3}>\u306B\u3088\u3063\u3066\u767A\u884C\u3055\u308C\u308B\u8A3C\u660E\u66F8({2})\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u540D: {5}"}, {"Enter.key.password.for.alias.", "<{0}>\u306E\u30AD\u30FC\u30FB\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044"}, {".RETURN.if.same.as.keystore.password.", "\t(\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u540C\u3058\u5834\u5408\u306FRETURN\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044): "}, @@ -387,8 +394,8 @@ public class Resources_ja extends java.util.ListResourceBundle { {".WARNING.WARNING.WARNING.", "***************** WARNING WARNING WARNING *****************"}, {"Signer.d.", "\u7F72\u540D\u8005\u756A\u53F7%d:"}, + {"Certificate.d.", "\u8A3C\u660E\u66F8#%d:"}, {"Timestamp.", "\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7:"}, - {"Signature.", "\u7F72\u540D:"}, {"Certificate.owner.", "\u8A3C\u660E\u66F8\u306E\u6240\u6709\u8005: "}, {"Not.a.signed.jar.file", "\u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u3042\u308A\u307E\u305B\u3093"}, {"No.certificate.from.the.SSL.server", @@ -451,6 +458,9 @@ public class Resources_ja extends java.util.ListResourceBundle { {"the.input", "\u5165\u529B"}, {"reply", "\u5FDC\u7B54"}, {"one.in.many", "%1$s #%2$d / %3$d"}, + {"one.in.many1", "%1$s #%2$d"}, + {"one.in.many2", "\u7F72\u540D\u8005\u306E%1$s #%2$d"}, + {"one.in.many3", "\u7F72\u540D\u8005\u306E%1$s #%2$d #%3$d"}, {"alias.in.cacerts", "cacerts\u5185\u306E\u767A\u884C\u8005<%s>"}, {"alias.in.keystore", "\u767A\u884C\u8005<%s>"}, {"with.weak", "%s (\u5F31)"}, @@ -473,7 +483,6 @@ public class Resources_ja extends java.util.ListResourceBundle { {"backup.keystore.warning", "\u5143\u306E\u30AD\u30FC\u30B9\u30C8\u30A2\"%1$s\"\u306F\"%3$s\"\u3068\u3057\u3066\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3055\u308C\u307E\u3059..."}, {"importing.keystore.status", "\u30AD\u30FC\u30B9\u30C8\u30A2%1$s\u3092%2$s\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u3059..."}, {"keyalg.option.missing.error", "-keyalg\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"}, - {"showinfo.no.option", "-showinfo\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u305B\u3093\u3002\"keytool -showinfo -tls\"\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, }; diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java index dfe71431c28e2a47374e91530ef7fdb89bb0bea4..520c55796efa3d239c94c927791621196ab9760d 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -96,6 +96,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"Changes.the.store.password.of.a.keystore", "\u66F4\u6539\u5BC6\u94A5\u5E93\u7684\u5B58\u50A8\u53E3\u4EE4"}, //-storepasswd {"showinfo.command.help", "\u663E\u793A\u5B89\u5168\u76F8\u5173\u4FE1\u606F"}, + {"Prints.the.program.version", "\u8F93\u51FA\u7A0B\u5E8F\u7248\u672C"}, // keytool: help: options {"alias.name.of.the.entry.to.process", @@ -159,6 +160,10 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u4EE5 RFC \u6837\u5F0F\u8F93\u51FA"}, //-rfc {"signature.algorithm.name", "\u7B7E\u540D\u7B97\u6CD5\u540D\u79F0"}, //-sigalg + {"signer.alias", + "\u7B7E\u540D\u8005\u522B\u540D"}, //-signer + {"signer.key.password", + "\u7B7E\u540D\u8005\u5BC6\u94A5\u5BC6\u7801"}, //-signerkeypass {"source.alias", "\u6E90\u522B\u540D"}, //-srcalias {"source.key.password", @@ -299,6 +304,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u672A\u751F\u6210\u5BC6\u94A5\u5BF9, \u522B\u540D <{0}> \u5DF2\u7ECF\u5B58\u5728"}, {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for", "\u6B63\u5728\u4E3A\u4EE5\u4E0B\u5BF9\u8C61\u751F\u6210 {0} \u4F4D{1}\u5BC6\u94A5\u5BF9\u548C\u81EA\u7B7E\u540D\u8BC1\u4E66 ({2}) (\u6709\u6548\u671F\u4E3A {3} \u5929):\n\t {4}"}, + {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for", + "\u6B63\u5728\u4E3A\u4EE5\u4E0B\u5BF9\u8C61\u751F\u6210 {0} \u4F4D {1} \u5BC6\u94A5\u5BF9\u548C\u7531 <{3}> \u9881\u53D1\u7684\u8BC1\u4E66 ({2})\uFF08\u6709\u6548\u671F\u4E3A {4} \u5929\uFF09\uFF1A\n\t {5}"}, {"Enter.key.password.for.alias.", "\u8F93\u5165 <{0}> \u7684\u5BC6\u94A5\u53E3\u4EE4"}, {".RETURN.if.same.as.keystore.password.", "\t(\u5982\u679C\u548C\u5BC6\u94A5\u5E93\u53E3\u4EE4\u76F8\u540C, \u6309\u56DE\u8F66): "}, @@ -387,8 +394,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {".WARNING.WARNING.WARNING.", "***************** WARNING WARNING WARNING *****************"}, {"Signer.d.", "\u7B7E\u540D\u8005 #%d:"}, + {"Certificate.d.", "\u8BC1\u4E66 #%d\uFF1A"}, {"Timestamp.", "\u65F6\u95F4\u6233:"}, - {"Signature.", "\u7B7E\u540D:"}, {"Certificate.owner.", "\u8BC1\u4E66\u6240\u6709\u8005: "}, {"Not.a.signed.jar.file", "\u4E0D\u662F\u5DF2\u7B7E\u540D\u7684 jar \u6587\u4EF6"}, {"No.certificate.from.the.SSL.server", @@ -451,6 +458,9 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"the.input", "\u8F93\u5165"}, {"reply", "\u56DE\u590D"}, {"one.in.many", "%1$s #%2$d/%3$d"}, + {"one.in.many1", "%1$s #%2$d"}, + {"one.in.many2", "\u7B7E\u540D\u8005 #%2$d \u7684 %1$s"}, + {"one.in.many3", "\u7B7E\u540D\u8005 #%3$d \u7684 %1$s #%2$d"}, {"alias.in.cacerts", "cacerts \u4E2D\u7684\u53D1\u5E03\u8005 <%s>"}, {"alias.in.keystore", "\u53D1\u5E03\u8005 <%s>"}, {"with.weak", "%s (\u5F31)"}, @@ -473,7 +483,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"backup.keystore.warning", "\u5DF2\u5C06\u539F\u59CB\u5BC6\u94A5\u5E93 \"%1$s\" \u5907\u4EFD\u4E3A \"%3$s\"..."}, {"importing.keystore.status", "\u6B63\u5728\u5C06\u5BC6\u94A5\u5E93 %1$s \u5BFC\u5165\u5230 %2$s..."}, {"keyalg.option.missing.error", "\u5FC5\u987B\u6307\u5B9A -keyalg \u9009\u9879\u3002"}, - {"showinfo.no.option", "-showinfo \u7F3A\u5C11\u9009\u9879\u3002\u8BF7\u5C1D\u8BD5\u4F7F\u7528 \"keytool -showinfo -tls\"\u3002"}, }; diff --git a/src/java.base/share/classes/sun/security/util/AuthResources_de.java b/src/java.base/share/classes/sun/security/util/AuthResources_de.java index 9775c7e4456db4c39a85618254fb9748cd6c9654..03b919626de19be935d7d62898c3f7bc4bced8c1 100644 --- a/src/java.base/share/classes/sun/security/util/AuthResources_de.java +++ b/src/java.base/share/classes/sun/security/util/AuthResources_de.java @@ -88,7 +88,7 @@ public class AuthResources_de extends java.util.ListResourceBundle { {"Keystore.alias.","Keystore-Alias: "}, {"Keystore.password.","Keystore-Kennwort: "}, {"Private.key.password.optional.", - "Private Key-Kennwort (optional): "}, + "Private-Key-Kennwort (optional): "}, // com.sun.security.auth.module.Krb5LoginModule {"Kerberos.username.defUsername.", 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/PropertyExpander.java b/src/java.base/share/classes/sun/security/util/PropertyExpander.java index b458439cb96d27434c7d91947593a36d2092435c..92daa46ce4debe95c94bd505b925cd5cbf622dfc 100644 --- a/src/java.base/share/classes/sun/security/util/PropertyExpander.java +++ b/src/java.base/share/classes/sun/security/util/PropertyExpander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, 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 @@ -63,7 +63,7 @@ public class PropertyExpander { if (value == null) return null; - int p = value.indexOf("${", 0); + int p = value.indexOf("${"); // no special characters if (p == -1) return value; diff --git a/src/java.base/share/classes/sun/security/util/Resources_de.java b/src/java.base/share/classes/sun/security/util/Resources_de.java index c36e24ac584b49ffd0c7d7df0324831698c9ee0b..57e2c8da8636a4110d01924532fdd15d144d7550 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_de.java +++ b/src/java.base/share/classes/sun/security/util/Resources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -66,8 +66,6 @@ public class Resources_de extends java.util.ListResourceBundle { {"Subject.", "Subjekt:\n"}, {".Principal.", "\tPrincipal: "}, {".Public.Credential.", "\t\u00D6ffentliche Zugangsdaten: "}, - {".Private.Credentials.inaccessible.", - "\tKein Zugriff auf private Zugangsdaten\n"}, {".Private.Credential.", "\tPrivate Zugangsdaten: "}, {".Private.Credential.inaccessible.", "\tKein Zugriff auf private Zugangsdaten\n"}, @@ -89,16 +87,6 @@ public class Resources_de extends java.util.ListResourceBundle { "Ung\u00FCltiger Nullwert f\u00FCr CallbackHandler angegeben"}, {"null.subject.logout.called.before.login", "Nullsubjekt - Abmeldung vor Anmeldung aufgerufen"}, - {"unable.to.instantiate.LoginModule.module.because.it.does.not.provide.a.no.argument.constructor", - "LoginModule {0} kann nicht instanziiert werden, da es keinen argumentlosen Constructor angibt"}, - {"unable.to.instantiate.LoginModule", - "LoginModule kann nicht instanziiert werden"}, - {"unable.to.instantiate.LoginModule.", - "LoginModule kann nicht instanziiert werden: "}, - {"unable.to.find.LoginModule.class.", - "LoginModule-Klasse kann nicht gefunden werden: "}, - {"unable.to.access.LoginModule.", - "Kein Zugriff auf LoginModule m\u00F6glich: "}, {"Login.Failure.all.modules.ignored", "Anmeldefehler: Alle Module werden ignoriert"}, @@ -150,11 +138,6 @@ public class Resources_de extends java.util.ListResourceBundle { // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", "Kennwort f\u00FCr PKCS11-Token [{0}]: "}, - - /* --- DEPRECATED --- */ - // javax.security.auth.Policy - {"unable.to.instantiate.Subject.based.policy", - "Subjektbasierte Policy kann nicht instanziiert werden"} }; diff --git a/src/java.base/share/classes/sun/security/util/Resources_ja.java b/src/java.base/share/classes/sun/security/util/Resources_ja.java index 195d71010a6fbf1f3f583d6dfd3bb682f8303d1a..1293a48aabc4be6e753b156570eab2d7ee3d2106 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_ja.java +++ b/src/java.base/share/classes/sun/security/util/Resources_ja.java @@ -66,8 +66,6 @@ public class Resources_ja extends java.util.ListResourceBundle { {"Subject.", "\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8:\n"}, {".Principal.", "\t\u30D7\u30EA\u30F3\u30B7\u30D1\u30EB: "}, {".Public.Credential.", "\t\u516C\u958B\u8CC7\u683C: "}, - {".Private.Credentials.inaccessible.", - "\t\u975E\u516C\u958B\u8CC7\u683C\u306B\u306F\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\n"}, {".Private.Credential.", "\t\u975E\u516C\u958B\u8CC7\u683C: "}, {".Private.Credential.inaccessible.", "\t\u975E\u516C\u958B\u8CC7\u683C\u306B\u306F\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\n"}, @@ -89,16 +87,6 @@ public class Resources_ja extends java.util.ListResourceBundle { "\u7121\u52B9\u306Anull CallbackHandler\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F"}, {"null.subject.logout.called.before.login", "null\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 - \u30ED\u30B0\u30A4\u30F3\u3059\u308B\u524D\u306B\u30ED\u30B0\u30A2\u30A6\u30C8\u304C\u547C\u3073\u51FA\u3055\u308C\u307E\u3057\u305F"}, - {"unable.to.instantiate.LoginModule.module.because.it.does.not.provide.a.no.argument.constructor", - "LoginModule {0}\u306F\u5F15\u6570\u3092\u53D6\u3089\u306A\u3044\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u3092\u6307\u5B9A\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093"}, - {"unable.to.instantiate.LoginModule", - "LoginModule\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093"}, - {"unable.to.instantiate.LoginModule.", - "LoginModule\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093: "}, - {"unable.to.find.LoginModule.class.", - "LoginModule\u30AF\u30E9\u30B9\u3092\u691C\u51FA\u3067\u304D\u307E\u305B\u3093: "}, - {"unable.to.access.LoginModule.", - "LoginModule\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093: "}, {"Login.Failure.all.modules.ignored", "\u30ED\u30B0\u30A4\u30F3\u5931\u6557: \u3059\u3079\u3066\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u7121\u8996\u3055\u308C\u307E\u3059"}, @@ -150,11 +138,6 @@ public class Resources_ja extends java.util.ListResourceBundle { // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", "PKCS11\u30C8\u30FC\u30AF\u30F3[{0}]\u30D1\u30B9\u30EF\u30FC\u30C9: "}, - - /* --- DEPRECATED --- */ - // javax.security.auth.Policy - {"unable.to.instantiate.Subject.based.policy", - "\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u30FB\u30D9\u30FC\u30B9\u306E\u30DD\u30EA\u30B7\u30FC\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093"} }; diff --git a/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java b/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java index 35d648bd3a47250acf85180ae90c0432fad87e90..5376ff5efd3531ad48839dde0cbc3a4ad045146f 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java +++ b/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java @@ -66,8 +66,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"Subject.", "\u4E3B\u4F53: \n"}, {".Principal.", "\t\u4E3B\u7528\u6237: "}, {".Public.Credential.", "\t\u516C\u5171\u8EAB\u4EFD\u8BC1\u660E: "}, - {".Private.Credentials.inaccessible.", - "\t\u65E0\u6CD5\u8BBF\u95EE\u4E13\u7528\u8EAB\u4EFD\u8BC1\u660E\n"}, {".Private.Credential.", "\t\u4E13\u7528\u8EAB\u4EFD\u8BC1\u660E: "}, {".Private.Credential.inaccessible.", "\t\u65E0\u6CD5\u8BBF\u95EE\u4E13\u7528\u8EAB\u4EFD\u8BC1\u660E\n"}, @@ -89,16 +87,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u63D0\u4F9B\u4E86\u65E0\u6548\u7684\u7A7A CallbackHandler"}, {"null.subject.logout.called.before.login", "\u7A7A\u4E3B\u4F53 - \u5728\u767B\u5F55\u4E4B\u524D\u8C03\u7528\u4E86\u6CE8\u9500"}, - {"unable.to.instantiate.LoginModule.module.because.it.does.not.provide.a.no.argument.constructor", - "\u65E0\u6CD5\u5B9E\u4F8B\u5316 LoginModule, {0}, \u56E0\u4E3A\u5B83\u672A\u63D0\u4F9B\u4E00\u4E2A\u65E0\u53C2\u6570\u6784\u9020\u5668"}, - {"unable.to.instantiate.LoginModule", - "\u65E0\u6CD5\u5B9E\u4F8B\u5316 LoginModule"}, - {"unable.to.instantiate.LoginModule.", - "\u65E0\u6CD5\u5B9E\u4F8B\u5316 LoginModule: "}, - {"unable.to.find.LoginModule.class.", - "\u65E0\u6CD5\u627E\u5230 LoginModule \u7C7B: "}, - {"unable.to.access.LoginModule.", - "\u65E0\u6CD5\u8BBF\u95EE LoginModule: "}, {"Login.Failure.all.modules.ignored", "\u767B\u5F55\u5931\u8D25: \u5FFD\u7565\u6240\u6709\u6A21\u5757"}, @@ -150,11 +138,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", "PKCS11 \u6807\u8BB0 [{0}] \u53E3\u4EE4: "}, - - /* --- DEPRECATED --- */ - // javax.security.auth.Policy - {"unable.to.instantiate.Subject.based.policy", - "\u65E0\u6CD5\u5B9E\u4F8B\u5316\u57FA\u4E8E\u4E3B\u9898\u7684\u7B56\u7565"} }; 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 166c4a5130f7c1efa024bac6c164d31a7979a4fb..c358cc663543843a05e17bc9ae081c7c76203c1a 100644 --- a/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java +++ b/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.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 @@ -27,9 +27,12 @@ package sun.security.util; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.PatternSyntaxException; import java.security.InvalidParameterException; import java.security.ProviderException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; import sun.security.action.GetPropertyAction; /** @@ -43,11 +46,11 @@ public final class SecurityProviderConstants { private static final Debug debug = Debug.getInstance("jca", "ProviderConfig"); - // cache for provider aliases; key is the standard algorithm name + // Cache for provider aliases; key is the standard algorithm name // value is the associated aliases List private static final ConcurrentHashMap> aliasesMap; - // utility method for generating aliases list using the supplied + // Utility method for generating aliases list using the supplied // 'oid' and 'extraAliases', then store into "aliasesMap" cache under the // key 'stdName' private static List store(String stdName, KnownOIDs oid, @@ -75,7 +78,7 @@ public final class SecurityProviderConstants { return value; } - // returns an aliases List for the specified algorithm name o + // Return an aliases List for the specified algorithm name o // NOTE: exception is thrown if no aliases nor oid found, so // only call this method if aliases are expected public static List getAliases(String o) { @@ -105,6 +108,25 @@ public final class SecurityProviderConstants { } } + public static final int getDefAESKeySize() { + int currVal = DEF_AES_KEY_SIZE.get(); + if (currVal == -1) { + int v = 256; // default AES key size + try { + // adjust if crypto policy only allows a smaller value + int max = Cipher.getMaxAllowedKeyLength("AES"); + if (v > max) { + v = max; + } + } catch (NoSuchAlgorithmException ne) { + // should never happen; ignore and use the default + } + DEF_AES_KEY_SIZE.compareAndSet(-1, v); + currVal = v; + } + return currVal; + } + public static final int DEF_DSA_KEY_SIZE; public static final int DEF_RSA_KEY_SIZE; public static final int DEF_RSASSA_PSS_KEY_SIZE; @@ -112,6 +134,11 @@ public final class SecurityProviderConstants { public static final int DEF_EC_KEY_SIZE; public static final int DEF_ED_KEY_SIZE; public static final int DEF_XEC_KEY_SIZE; + // The logic for finding the max allowable value in getDefAESKeySize() + // interferes with provider loading logic and may lead to deadlocks if + // called inside a static block. So, it is deferred to a later time when + // DEF_AES_KEY_SIZE is actually used/needed. + private static final AtomicInteger DEF_AES_KEY_SIZE; private static final String KEY_LENGTH_PROP = "jdk.security.defaultKeySize"; @@ -120,12 +147,13 @@ public final class SecurityProviderConstants { String keyLengthStr = GetPropertyAction.privilegedGetProperty (KEY_LENGTH_PROP); int dsaKeySize = 2048; - int rsaKeySize = 2048; + int rsaKeySize = 3072; int rsaSsaPssKeySize = rsaKeySize; // default to same value as RSA - int dhKeySize = 2048; - int ecKeySize = 256; + int dhKeySize = 3072; + int ecKeySize = 384; int edKeySize = 255; int xecKeySize = 255; + int aesKeySize = -1; // needs to check crypto policy if (keyLengthStr != null) { try { @@ -167,6 +195,8 @@ public final class SecurityProviderConstants { edKeySize = value; } else if (algoName.equals("XDH")) { xecKeySize = value; + } else if (algoName.equals("AES")) { + aesKeySize = value; } else { if (debug != null) { debug.println("Ignoring unsupported algo in " + @@ -195,6 +225,7 @@ public final class SecurityProviderConstants { DEF_EC_KEY_SIZE = ecKeySize; DEF_ED_KEY_SIZE = edKeySize; DEF_XEC_KEY_SIZE = xecKeySize; + DEF_AES_KEY_SIZE = new AtomicInteger(aesKeySize); // Set up aliases with default mappings // This is needed when the mapping contains non-oid 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 ec86df854fcc50827614f152f89bf31dc0dc8c2c..8fe2d4deebe8e37826aa5a60a44cc40e61f3d15c 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureUtil.java +++ b/src/java.base/share/classes/sun/security/util/SignatureUtil.java @@ -60,13 +60,11 @@ public class SignatureUtil { if (algName.startsWith("OID.")) { algName = algName.substring(4); } - KnownOIDs ko = KnownOIDs.findMatch(algName); if (ko != null) { return ko.stdName().toUpperCase(Locale.ENGLISH); } } - return algName; } @@ -491,12 +489,11 @@ public class SignatureUtil { * @return the default alg, might be null if unsupported */ public static String getDefaultSigAlgForKey(PrivateKey k) { - String kAlg = k.getAlgorithm(); - return switch (kAlg.toUpperCase(Locale.ENGLISH)) { - case "DSA", "RSA" -> ifcFfcStrength(KeyUtil.getKeySize(k)) - + "with" + kAlg; - case "EC" -> ecStrength(KeyUtil.getKeySize(k)) - + "withECDSA"; + String kAlg = k.getAlgorithm().toUpperCase(Locale.ENGLISH); + return switch (kAlg) { + case "DSA" -> "SHA256withDSA"; + case "RSA" -> ifcFfcStrength(KeyUtil.getKeySize(k)) + "withRSA"; + case "EC" -> ecStrength(KeyUtil.getKeySize(k)) + "withECDSA"; case "EDDSA" -> k instanceof EdECPrivateKey ? ((EdECPrivateKey) k).getParams().getName() : kAlg; @@ -521,11 +518,16 @@ public class SignatureUtil { 64, PSSParameterSpec.TRAILER_FIELD_BC); } - // The following values are from SP800-57 part 1 rev 4 tables 2 and 3 + // SP800-57 part 1 rev5 table 2 "Comparable security strengths of + // symmetric block cipher and asymmetric-key algorithms", and table 3 + // "Maximum security strengths for hash and hash-based functions" + // define security strength for various algorithms. + // Besides matching the security strength, the default algorithms may + // also be chosen based on various recommendations such as NIST CNSA. /** - * Return the default message digest algorithm with the same security - * strength as the specified EC key size. + * Return the default message digest algorithm based on the specified + * EC key size. * * Attention: sync with the @implNote inside * {@link jdk.security.jarsigner.JarSigner.Builder#getDefaultSignatureAlgorithm}. @@ -533,27 +535,27 @@ public class SignatureUtil { private static String ecStrength (int bitLength) { if (bitLength >= 512) { // 256 bits of strength return "SHA512"; - } else if (bitLength >= 384) { // 192 bits of strength + } else { + // per CNSA, use SHA-384 return "SHA384"; - } else { // 128 bits of strength and less - return "SHA256"; } } /** - * Return the default message digest algorithm with the same security - * strength as the specified IFC/FFC key size. + * Return the default message digest algorithm based on both the + * security strength of the specified IFC/FFC key size, i.e. RSA, + * RSASSA-PSS, and the recommendation from NIST CNSA, e.g. use SHA-384 + * and min 3072-bit. * * Attention: sync with the @implNote inside * {@link jdk.security.jarsigner.JarSigner.Builder#getDefaultSignatureAlgorithm}. */ - private static String ifcFfcStrength (int bitLength) { - if (bitLength > 7680) { // 256 bits + private static String ifcFfcStrength(int bitLength) { + if (bitLength > 7680) { // 256 bits security strength return "SHA512"; - } else if (bitLength > 3072) { // 192 bits - return "SHA384"; - } else { // 128 bits and less - return "SHA256"; + } else { + // per CNSA, use SHA-384 unless keysize is too small + return (bitLength >= 624 ? "SHA384" : "SHA256"); } } } diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index 5f2403f3b40defc0799b7a4bdcee558d2835fb38..2475539a45ad65e073d3ec4fa211c7a92c9169a7 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.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 @@ -63,7 +63,7 @@ public class AlgorithmId implements Serializable, DerEncoder { private static final long serialVersionUID = 7205873507486557157L; /** - * The object identitifer being used for this algorithm. + * The object identifier being used for this algorithm. */ private ObjectIdentifier algid; @@ -584,7 +584,7 @@ public class AlgorithmId implements Serializable, DerEncoder { String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); int index; if (upperCaseAlias.startsWith("ALG.ALIAS") && - (index = upperCaseAlias.indexOf("OID.", 0)) != -1) { + (index = upperCaseAlias.indexOf("OID.")) != -1) { index += "OID.".length(); if (index == alias.length()) { // invalid alias entry diff --git a/src/java.base/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java b/src/java.base/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java index 69459fb6ef04bf670bd7062f9801782de9fca4c3..f25110dfbbe4705f35c090717567fa0bbeaa9039 100644 --- a/src/java.base/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java +++ b/src/java.base/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java @@ -43,7 +43,7 @@ import sun.security.util.DerValue; * certificate that identifies the specific OCSP Responder to use when * performing on-line validation of that certificate. *

    - * This extension is defined in + * This extension is defined in * Internet X.509 PKI Certificate and Certificate Revocation List * (CRL) Profile. The profile permits * the extension to be included in end-entity or CA certificates, diff --git a/src/java.base/share/classes/sun/security/x509/DNSName.java b/src/java.base/share/classes/sun/security/x509/DNSName.java index ee9e8a9c0a0baf49b6a2d858fc35a4bf8c86393f..e2ad7df98e224c81c1f65d6e66c2719db79fc6d5 100644 --- a/src/java.base/share/classes/sun/security/x509/DNSName.java +++ b/src/java.base/share/classes/sun/security/x509/DNSName.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 @@ -100,7 +100,7 @@ public class DNSName implements GeneralNameInterface { if (alphaDigits.indexOf(name.charAt(startIndex)) < 0) { // Checking to make sure the wildcard only appears in the first component, // and it has to be at least 3-char long with the form of *.[alphaDigit] - if ((name.length() < 3) || (name.indexOf('*', 0) != 0) || + if ((name.length() < 3) || (name.indexOf('*') != 0) || (name.charAt(startIndex+1) != '.') || (alphaDigits.indexOf(name.charAt(startIndex+2)) < 0)) throw new IOException("DNSName components must begin with a letter, digit, " diff --git a/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java b/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java index 5933758874a79123ddbf9a51f116b92f96c3e16c..10e36f2b4ae06d0beee54881067661696f18c712 100644 --- a/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java +++ b/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java @@ -42,7 +42,7 @@ import java.math.BigInteger; * *

    * The extension is defined in Section 5.2.4 of - * Internet X.509 PKI + * Internet X.509 PKI * Certificate and Certificate Revocation List (CRL) Profile. * *

    diff --git a/src/java.base/share/classes/sun/security/x509/FreshestCRLExtension.java b/src/java.base/share/classes/sun/security/x509/FreshestCRLExtension.java index 84dcb284cab0355eb8817752eead429a52d57ff7..4cc0b5180b59f8df2764c95b982a650e55aabf6d 100644 --- a/src/java.base/share/classes/sun/security/x509/FreshestCRLExtension.java +++ b/src/java.base/share/classes/sun/security/x509/FreshestCRLExtension.java @@ -42,7 +42,7 @@ import sun.security.util.*; * *

    * The extension is defined in Section 5.2.6 of - * Internet X.509 PKI + * Internet X.509 PKI * Certificate and Certificate Revocation List (CRL) Profile. * *

    diff --git a/src/java.base/share/classes/sun/security/x509/IssuingDistributionPointExtension.java b/src/java.base/share/classes/sun/security/x509/IssuingDistributionPointExtension.java index d810cf012ae4672b6fd65005f5c8aafffaafcc2e..f214cddf650505fd307eb27c6ddfd766e8a42c4f 100644 --- a/src/java.base/share/classes/sun/security/x509/IssuingDistributionPointExtension.java +++ b/src/java.base/share/classes/sun/security/x509/IssuingDistributionPointExtension.java @@ -46,7 +46,7 @@ import sun.security.util.DerValue; * *

    * The extension is defined in Section 5.2.5 of - * Internet X.509 PKI + * Internet X.509 PKI * Certificate and Certificate Revocation List (CRL) Profile. * *

    diff --git a/src/java.base/share/classes/sun/security/x509/SubjectInfoAccessExtension.java b/src/java.base/share/classes/sun/security/x509/SubjectInfoAccessExtension.java index 0acdf96057f843126dd73fc17ddbdcf39fb568c3..09636a7ebb2163de313ed5123d974737d5681466 100644 --- a/src/java.base/share/classes/sun/security/x509/SubjectInfoAccessExtension.java +++ b/src/java.base/share/classes/sun/security/x509/SubjectInfoAccessExtension.java @@ -48,7 +48,7 @@ import sun.security.util.DerValue; * included in end entity or CA certificates. Conforming CAs MUST mark * this extension as non-critical. *

    - * This extension is defined in + * This extension is defined in * Internet X.509 PKI Certificate and Certificate Revocation List * (CRL) Profile. The profile permits * the extension to be included in end-entity or CA certificates, diff --git a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java index 551e38ad31cee6c67a4111bc86815c4bfa45981b..f721b8156dcf166bcef547b307273d9de126b33c 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java @@ -54,7 +54,7 @@ import sun.security.util.*; * signature BIT STRING } * * More information can be found in - * RFC 5280: Internet X.509 + * RFC 5280: Internet X.509 * Public Key Infrastructure Certificate and CRL Profile. *

    * The ASN.1 definition of tbsCertList is: diff --git a/src/java.base/share/classes/sun/util/locale/provider/JRELocaleConstants.java b/src/java.base/share/classes/sun/util/locale/provider/JRELocaleConstants.java index ea511c5bbc6b54948ed1bea60e9ea860888feada..f54f8d5b68eb19b97719461a27d343b169731344 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/JRELocaleConstants.java +++ b/src/java.base/share/classes/sun/util/locale/provider/JRELocaleConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -35,10 +35,10 @@ import java.util.Locale; * @author Masayoshi Okutsu */ public class JRELocaleConstants { - public static final Locale JA_JP_JP = new Locale("ja", "JP", "JP"); - public static final Locale NO_NO_NY = new Locale("no", "NO", "NY"); - public static final Locale TH_TH = new Locale("th", "TH"); - public static final Locale TH_TH_TH = new Locale("th", "TH", "TH"); + public static final Locale JA_JP_JP = Locale.of("ja", "JP", "JP"); + public static final Locale NO_NO_NY = Locale.of("no", "NO", "NY"); + public static final Locale TH_TH = Locale.of("th", "TH"); + public static final Locale TH_TH_TH = Locale.of("th", "TH", "TH"); private JRELocaleConstants() { } diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java index 18bac98d9419975bb6445588ece0d9fb3a838be7..0cfbf24ad836066a8641ed07f7bea2e2dae89b95 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.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 @@ -369,7 +369,7 @@ public final class LocaleServiceProviderPool { "A locale(" + locale + ") has non-empty extensions, but has illformed fields."); // Fallback - script field will be lost. - lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant()); + lookupLocale = Locale.of(locale.getLanguage(), locale.getCountry(), locale.getVariant()); } } return lookupLocale; 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/src/java.base/share/classes/sun/util/resources/LocaleData.java b/src/java.base/share/classes/sun/util/resources/LocaleData.java index 4240352e8318d0765a5eba32d4c149e3696d8d40..7d9af41811cbe1c4bf224d19074b43295ece723c 100644 --- a/src/java.base/share/classes/sun/util/resources/LocaleData.java +++ b/src/java.base/share/classes/sun/util/resources/LocaleData.java @@ -246,7 +246,7 @@ public class LocaleData { private static final LocaleDataStrategy INSTANCE = new LocaleDataStrategy(); // TODO: avoid hard-coded Locales private static final Set JAVA_BASE_LOCALES - = Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US, new Locale("en", "US", "POSIX")); + = Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US, Locale.of("en", "US", "POSIX")); private LocaleDataStrategy() { } diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 91b3a01ee577f574ebbe060ee08042c289eca43b..2c094c9f19d33482ca6883283a357142a369d029 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -701,6 +701,16 @@ jdk.security.legacyAlgorithms=SHA1, \ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ DSA keySize < 1024, SHA1 denyAfter 2019-01-01 +# +# Disabled message digest algorithms for use with plaintext +# HTTP Digest authentication (java.net.HttpURLConnection). +# This includes HTTPS Digest authentication to proxies. +# This may be overridden by setting the networking (or system) +# property "http.auth.digest.reEnabledAlgorithms" to a comma +# separated list of algorithms to be allowed. +# +http.auth.digest.disabledAlgorithms = MD5, SHA-1 + # # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS/DTLS) processing 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/make/data/publicsuffixlist/VERSION b/src/java.base/share/data/publicsuffixlist/VERSION similarity index 100% rename from make/data/publicsuffixlist/VERSION rename to src/java.base/share/data/publicsuffixlist/VERSION diff --git a/make/data/publicsuffixlist/public_suffix_list.dat b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat similarity index 100% rename from make/data/publicsuffixlist/public_suffix_list.dat rename to src/java.base/share/data/publicsuffixlist/public_suffix_list.dat diff --git a/make/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION similarity index 98% rename from make/data/tzdata/VERSION rename to src/java.base/share/data/tzdata/VERSION index 3a40c9103336dd787555918125044d61d62f1810..bc830a3a5ef737afa535f46512f743f5494d533d 100644 --- a/make/data/tzdata/VERSION +++ b/src/java.base/share/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2021e +tzdata2022a diff --git a/make/data/tzdata/africa b/src/java.base/share/data/tzdata/africa similarity index 99% rename from make/data/tzdata/africa rename to src/java.base/share/data/tzdata/africa index 0f367713ea900d457b14a23963854bc94c1c1414..5466bbcc87b80967b42c44abd51435753c58a716 100644 --- a/make/data/tzdata/africa +++ b/src/java.base/share/data/tzdata/africa @@ -941,6 +941,10 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis # (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) # (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) # (setq islamic-year (+ 1 islamic-year)))) +# +# From Milamber (2021-03-31, 2022-03-10), confirming these predictions: +# https://www.mmsp.gov.ma/fr/actualites.aspx?id=2076 +# https://www.ecoactu.ma/horaires-administration-ramadan-gmtheure-gmt-a-partir-de-dimanche-27-mars/ # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Morocco 1939 only - Sep 12 0:00 1:00 - 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 99% rename from make/data/tzdata/asia rename to src/java.base/share/data/tzdata/asia index cfe48745e2459fc3a5cbdbe803a983fa372e58d1..4aaaf146b0f4e4d83925d3cd9b6a0469136cd7dd 100644 --- a/make/data/tzdata/asia +++ b/src/java.base/share/data/tzdata/asia @@ -3429,8 +3429,12 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # ... winter time will begin in Palestine from Friday 10-29, 01:00 AM # by 60 minutes backwards. # -# From Paul Eggert (2021-10-20): -# Guess future fall transitions on October's last Friday at 01:00. +# From Tim Parenti (2021-10-25), per Paul Eggert (2021-10-24): +# Guess future fall transitions at 01:00 on the Friday preceding October's +# last Sunday (i.e., Fri>=23), as this is more consistent with recent practice. + +# From Heba Hamad (2022-03-10): +# summer time will begin in Palestine from Sunday 03-27-2022, 00:00 AM. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -3466,9 +3470,10 @@ Rule Palestine 2016 2018 - Mar Sat>=24 1:00 1:00 S Rule Palestine 2016 2018 - Oct Sat>=24 1:00 0 - Rule Palestine 2019 only - Mar 29 0:00 1:00 S Rule Palestine 2019 only - Oct Sat>=24 0:00 0 - -Rule Palestine 2020 max - Mar Sat>=24 0:00 1:00 S +Rule Palestine 2020 2021 - Mar Sat>=24 0:00 1:00 S Rule Palestine 2020 only - Oct 24 1:00 0 - -Rule Palestine 2021 max - Oct lastFri 1:00 0 - +Rule Palestine 2021 max - Oct Fri>=23 1:00 0 - +Rule Palestine 2022 max - Mar Sun>=25 0:00 1:00 S # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct 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 98% rename from make/data/tzdata/europe rename to src/java.base/share/data/tzdata/europe index 9b0b64aa3ebecea94677bf4119dd5b27271fd585..bc57e94e44f4fe212eceed3d918600572fe81d6c 100644 --- a/make/data/tzdata/europe +++ b/src/java.base/share/data/tzdata/europe @@ -2808,8 +2808,26 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr # says he remembers that Samara opted out of the 1992-01-19 exception # 2 days before the switch. # -# -# From Paul Eggert (2016-03-18): +# From Alois Treindl (2022-02-15): +# the Russian wikipedia page +# https://ru.wikipedia.org/wiki/Московское_время#Перемещение_границы_применения_московского_времени_на_восток +# contains the sentence (in Google translation) "In the autumn of +# 1981, Arkhangelsk, Vologda, Yaroslavl, Ivanovo, Vladimir, Ryazan, +# Lipetsk, Voronezh, Rostov-on-Don, Krasnodar and regions to the east +# of those named (about 30 in total) parted ways with Moscow time. +# However, the convenience of common time with Moscow turned out to be +# decisive - in 1982, these regions again switched to Moscow time." +# Shanks International atlas has similar information, and also the +# Russian book Zaitsev A., Kutalev D. A new astrologer's reference +# book. Coordinates of cities and time corrections, - The World of +# Urania, 2012 (Russian: Зайцев А., Куталёв Д., Новый справочник +# астролога. Координаты городов и временные поправки). +# To me it seems that an extra zone is needed, which starts with LMT +# util 1919, later follows Moscow since 1930, but deviates from it +# between 1 October 1981 until 1 April 1982. +# +# +# From Paul Eggert (2022-02-15): # Given the above, we appear to be missing some Zone entries for the # chaotic early 1980s in Russia. It's not clear what these entries # should be. For now, sweep this under the rug and just document the @@ -2856,7 +2874,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 1:00 C-Eur CE%sT 1944 Apr 13 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 - 2:00 - EET 1992 + 2:00 - EET 1992 Mar 20 # Central Crimea used Moscow time 1994/1997. # # From Paul Eggert (2006-03-22): @@ -2866,7 +2884,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 # sometime between the 1994 DST switches. Shanks & Pottenger simply say # 1994-09-25 03:00, but that can't be right. For now, guess it # changed in May. - 2:00 E-Eur EE%sT 1994 May + 2:00 C-Eur EE%sT 1994 May # From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev. 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s 3:00 1:00 MSD 1996 Oct 27 3:00s @@ -4033,6 +4051,27 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # Ukraine # +# From Alois Triendl (2014-03-01): +# REGULATION A N O V A on March 20, 1992 N 139 ... means that from +# 1992 on, Ukraine had DST with begin time at 02:00 am, on last Sunday +# in March, and end time 03:00 am, last Sunday in September.... +# CABINET OF MINISTERS OF UKRAINE RESOLUTION on May 13, 1996 N 509 +# "On the order of computation time on the territory of Ukraine" .... +# As this cabinet decision is from May 1996, it seems likely that the +# transition in March 1996, which predates it, was still at 2:00 am +# and not at 3:00 as would have been under EU rules. +# This is why I have set the change to EU rules into May 1996, +# so that the change in March is stil covered by the Ukraine rule. +# The next change in October 1996 happened under EU rules.... +# TZ database holds three other zones for Ukraine.... I have not yet +# worked out the consequences for these three zones, as we (me and my +# US colleague David Cochrane) are still trying to get more +# information upon these local deviations from Kiev rules. +# +# From Paul Eggert (2022-02-08): +# For now, assume that Ukraine's other three zones followed the same rules, +# except that Crimea switched to Moscow time in 1994 as described elsewhere. + # From Igor Karpov, who works for the Ukrainian Ministry of Justice, # via Garrett Wollman (2003-01-27): # BTW, I've found the official document on this matter. It's government @@ -4122,7 +4161,7 @@ Zone Europe/Kiev 2:02:04 - LMT 1880 1:00 C-Eur CE%sT 1943 Nov 6 3:00 Russia MSK/MSD 1990 Jul 1 2:00 2:00 1:00 EEST 1991 Sep 29 3:00 - 2:00 E-Eur EE%sT 1995 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Transcarpathia used CET 1990/1991. # "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but @@ -4135,8 +4174,8 @@ Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 1:00 - CET 1991 Mar 31 3:00 - 2:00 - EET 1992 - 2:00 E-Eur EE%sT 1995 + 2:00 - EET 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991. # "Zaporizhia" is the transliteration of the Ukrainian name, but @@ -4149,7 +4188,8 @@ Zone Europe/Zaporozhye 2:20:40 - LMT 1880 3:00 - MSK 1941 Aug 25 1:00 C-Eur CE%sT 1943 Oct 25 3:00 Russia MSK/MSD 1991 Mar 31 2:00 - 2:00 E-Eur EE%sT 1995 + 2:00 E-Eur EE%sT 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Vatican City 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 96% rename from make/data/tzdata/leapseconds rename to src/java.base/share/data/tzdata/leapseconds index cc514561ff177924dd0741b5b5f9f37c3b8526d2..776d25ab3674edaccb0ec3de640bb280bf527350 100644 --- a/make/data/tzdata/leapseconds +++ b/src/java.base/share/data/tzdata/leapseconds @@ -95,11 +95,11 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2022 Jun 28 00:00:00 +#Expires 2022 Dec 28 00:00:00 # POSIX timestamps for the data in this file: #updated 1467936000 (2016-07-08 00:00:00 UTC) -#expires 1656374400 (2022-06-28 00:00:00 UTC) +#expires 1672185600 (2022-12-28 00:00:00 UTC) -# Updated through IERS Bulletin C62 -# File expires on: 28 June 2022 +# Updated through IERS Bulletin C63 +# File expires on: 28 December 2022 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 97% rename from make/data/tzdata/southamerica rename to src/java.base/share/data/tzdata/southamerica index 503ed65f58036589e0a49de694077ca769a25a9e..b6e401ac2528f9be8dbc1a1c2cbb5234eb4685a2 100644 --- a/make/data/tzdata/southamerica +++ b/src/java.base/share/data/tzdata/southamerica @@ -1109,7 +1109,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Chile -# From Paul Eggert (2015-04-03): +# From Paul Eggert (2022-03-15): # Shanks & Pottenger says America/Santiago introduced standard time in # 1890 and rounds its UT offset to 70W40; guess that in practice this # was the same offset as in 1916-1919. It also says Pacific/Easter @@ -1132,7 +1132,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Historia de la hora oficial de Chile (retrieved 2012-10-24). See: # https://web.archive.org/web/20121024234627/http://www.horaoficial.cl/horaof.htm # A fancier Spanish version (requiring mouse-clicking) is at: -# http://www.horaoficial.cl/historia_hora.html +# http://www.horaoficial.cl/historia_hora.php # Conflicts between [1] and [2] were resolved as follows: # # - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites @@ -1141,7 +1141,8 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # - [1] says SMT was -4:42:45, [2] says Chile's official time from # 1916 to 1919 was -4:42:46.3, the meridian of Chile's National # Astronomical Observatory (OAN), then located in what is now -# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46. +# Quinta Normal in Santiago. Go with [1], as this matches the meridian +# referred to by the relevant Chilean laws to this day. # # - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites # Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2]. @@ -1163,6 +1164,32 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # this is known to work for DST transitions starting in 2008 and # may well be true for earlier transitions. +# From Tim Parenti (2022-03-15): +# For a brief period of roughly six weeks in 1946, DST was only observed on an +# emergency basis in specific regions of central Chile; namely, "the national +# territory between the provinces of Coquimbo and Concepción, inclusive". +# This was enacted by Decree 3,891, dated 1946-07-13, and took effect +# 1946-07-14 24:00, advancing these central regions to -03. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460715/#page/1 +# The decree contemplated "[t]hat this advancement of the Official Time, even +# though it has been proposed for the cities of Santiago and Valparaíso only, +# must be agreed with that of other cities, due to the connection of various +# activities that require it, such as, for example, the operation of rail +# services". It was originally set to expire after 30 days but was extended +# through 1946-08-31 by Decree 4,506, dated 1946-08-13. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460814/#page/1 +# +# Law Number 8,522, promulgated 1946-08-27, reunified Chilean clocks at their +# new "Summer Time" of -04, reckoned as that of "the meridian of the +# Astronomical Observatory of Lo Espejo, advanced by 42 minutes and 45 +# seconds". +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460828/#page/1 +# After a brief "Winter Time" stint at -05 beginning 1947-04-01, Law Number +# 8,777, promulgated 1947-05-17, established year-round -04 "from 23:00 on the +# second day after it is published in the 'Diario Oficial'." It was published +# on Monday 1947-05-19 and so took effect from Wednesday 1947-05-21 23:00. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19470519/#page/1 + # From Eduardo Krell (1995-10-19): # The law says to switch to DST at midnight [24:00] on the second SATURDAY # of October.... The law is the same for March and October. @@ -1321,12 +1348,12 @@ Rule Chile 2019 max - Sep Sun>=2 4:00u 1:00 - # IATA SSIM anomalies: (1992-02) says 1992-03-14; # (1996-09) says 1998-03-08. Ignore these. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone America/Santiago -4:42:46 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 # Santiago Mean Time +Zone America/Santiago -4:42:45 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 # Santiago Mean Time -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 @@ -1336,11 +1363,11 @@ Zone America/Santiago -4:42:46 - LMT 1890 -5:00 - -05 1947 May 21 23:00 -4:00 Chile -04/-03 Zone America/Punta_Arenas -4:43:40 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 + -4:42:45 - SMT 1910 Jan 10 -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 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/asm.md b/src/java.base/share/legal/asm.md index 707ecda7c0e19e9eeb526b8cc2598bd0a5ed3384..4b796017cec62fca37bf959ccb5e395d9d72b4b4 100644 --- a/src/java.base/share/legal/asm.md +++ b/src/java.base/share/legal/asm.md @@ -1,4 +1,4 @@ -## ASM Bytecode Manipulation Framework v8.0.1 +## ASM Bytecode Manipulation Framework v9.2 ### ASM License

    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/libnet/InetAddress.c b/src/java.base/share/native/libnet/InetAddress.c
    index 39b419d600e361cfd07a5d324ef111453937db1c..e759a064d256ecb3b6abd53371c2d34ceb242b13 100644
    --- a/src/java.base/share/native/libnet/InetAddress.c
    +++ b/src/java.base/share/native/libnet/InetAddress.c
    @@ -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
    @@ -76,8 +76,19 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
     /*
      * Class:     java_net_InetAddress
      * Method:    isIPv4Available
    + * Signature: ()Z
      */
     JNIEXPORT jboolean JNICALL
     Java_java_net_InetAddress_isIPv4Available(JNIEnv *env, jclass clazz) {
         return ipv4_available();
     }
    +
    +/*
    + * Class:     java_net_InetAddress
    + * Method:    isIPv6Supported
    + * Signature: ()Z
    + */
    +JNIEXPORT jboolean JNICALL
    +Java_java_net_InetAddress_isIPv6Supported(JNIEnv *env, jclass clazz) {
    +    return ipv6_available();
    +}
    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/share/native/libzip/zlib/ChangeLog b/src/java.base/share/native/libzip/zlib/ChangeLog
    index 30199a65a03daa6cdd55391a041d70fef5f19002..9dbeb5e5642b5f8cf27e0a45934c68f483a4de62 100644
    --- a/src/java.base/share/native/libzip/zlib/ChangeLog
    +++ b/src/java.base/share/native/libzip/zlib/ChangeLog
    @@ -304,7 +304,7 @@ Changes in 1.2.5.1 (10 Sep 2011)
     - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
     - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
     - Add debug records in assmebler code [Londer]
    -- Update RFC references to use http://tools.ietf.org/html/... [Li]
    +- Update RFC references to use https://tools.ietf.org/html/... [Li]
     - Add --archs option, use of libtool to configure for Mac OS X [Borstel]
     
     Changes in 1.2.5 (19 Apr 2010)
    diff --git a/src/java.base/share/native/libzip/zlib/README b/src/java.base/share/native/libzip/zlib/README
    index 51106de4753292ad59de03de9e634e6814eeb7a2..a0d208b770571658e46522c2ca4fa2a6a444f9fd 100644
    --- a/src/java.base/share/native/libzip/zlib/README
    +++ b/src/java.base/share/native/libzip/zlib/README
    @@ -3,7 +3,7 @@ ZLIB DATA COMPRESSION LIBRARY
     zlib 1.2.11 is a general purpose data compression library.  All the code is
     thread safe.  The data format used by the zlib library is described by RFCs
     (Request for Comments) 1950 to 1952 in the files
    -http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
    +https://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
     rfc1952 (gzip format).
     
     All functions of the compression library are documented in the file zlib.h
    diff --git a/src/java.base/share/native/libzip/zlib/deflate.c b/src/java.base/share/native/libzip/zlib/deflate.c
    index f30f71bdd799deb31c34aea462e1ab83b35e9236..f8d84da882aa6c2f1cf976e400e5de34c03e4962 100644
    --- a/src/java.base/share/native/libzip/zlib/deflate.c
    +++ b/src/java.base/share/native/libzip/zlib/deflate.c
    @@ -61,7 +61,7 @@
      *  REFERENCES
      *
      *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
    - *      Available in http://tools.ietf.org/html/rfc1951
    + *      Available in https://tools.ietf.org/html/rfc1951
      *
      *      A description of the Rabin and Karp algorithm is given in the book
      *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
    diff --git a/src/java.base/share/native/libzip/zlib/zlib.h b/src/java.base/share/native/libzip/zlib/zlib.h
    index e383d0e4508efea891aedf14c5e85cf721e02513..729c77ba165cc2b2401ff26b9c17ec5374313b5b 100644
    --- a/src/java.base/share/native/libzip/zlib/zlib.h
    +++ b/src/java.base/share/native/libzip/zlib/zlib.h
    @@ -48,7 +48,7 @@
     
     
       The data format used by the zlib library is described by RFCs (Request for
    -  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
    +  Comments) 1950 to 1952 in the files https://tools.ietf.org/html/rfc1950
       (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
     */
     
    diff --git a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
    index 5584aba125b4d71db9e593607dbe2828e22ecd29..6074d323fa576b41a64398137eb4fc5d5afaf2c6 100644
    --- a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
    +++ b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -37,7 +37,7 @@ import java.io.IOException;
      * and Linux.
      */
     
    -public class ResolverConfigurationImpl
    +public final class ResolverConfigurationImpl
         extends ResolverConfiguration
     {
         // Lock helds whilst loading configuration or checking
    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/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/net/dns/ResolverConfigurationImpl.java b/src/java.base/windows/classes/sun/net/dns/ResolverConfigurationImpl.java
    index ac7780b072decf4d6c6551867b27815bc878293c..c3cf072007f96a222435681cd5cfa934c404f5e2 100644
    --- a/src/java.base/windows/classes/sun/net/dns/ResolverConfigurationImpl.java
    +++ b/src/java.base/windows/classes/sun/net/dns/ResolverConfigurationImpl.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
    @@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit;
      * An implementation of sun.net.ResolverConfiguration for Windows.
      */
     
    -public class ResolverConfigurationImpl
    +public final class ResolverConfigurationImpl
         extends ResolverConfiguration
     {
         // Lock held whilst loading configuration or checking
    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/lang/model/util/ElementScanner14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java
    index ac1bc4976cac1ffdff4f543d04c1c18769c2d399..4365c6df53ca387a26d7efa71ba7b05510538182 100644
    --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java
    +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.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
    @@ -37,15 +37,16 @@ import static javax.lang.model.SourceVersion.*;
      * appropriate for the {@link SourceVersion#RELEASE_14 RELEASE_14}
      * source version.
      *
    - * The visitXyz methods in this
    - * class scan their component elements by calling {@code scan} on
    - * their {@linkplain Element#getEnclosedElements enclosed elements},
    - * {@linkplain ExecutableElement#getParameters parameters}, etc., as
    - * indicated in the individual method specifications.  A subclass can
    - * control the order elements are visited by overriding the
    - * visitXyz methods.  Note that clients of a scanner
    - * may get the desired behavior be invoking {@code v.scan(e, p)} rather
    - * than {@code v.visit(e, p)} on the root objects of interest.
    + * The visitXyz methods in this class scan their
    + * component elements by calling {@link ElementScanner6#scan(Element,
    + * Object) scan} on their {@linkplain Element#getEnclosedElements
    + * enclosed elements}, {@linkplain ExecutableElement#getParameters
    + * parameters}, etc., as indicated in the individual method
    + * specifications.  A subclass can control the order elements are
    + * visited by overriding the visitXyz methods.
    + * Note that clients of a scanner may get the desired behavior by
    + * invoking {@code v.scan(e, p)} rather than {@code v.visit(e, p)} on
    + * the root objects of interest.
      *
      * 

    When a subclass overrides a visitXyz method, the * new method can cause the enclosed elements to be scanned in the 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 b13bd3cd0cc7c387096da22c3ecc6b6784f80be3..c2b628b033c2c8d6dde434531191a6994d46b334 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 @@ -35,14 +35,16 @@ import static javax.lang.model.SourceVersion.*; * A scanning visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_6 RELEASE_6} * source version. The visitXyz methods in this - * class scan their component elements by calling {@code scan} on - * their {@linkplain Element#getEnclosedElements enclosed elements}, - * {@linkplain ExecutableElement#getParameters parameters}, etc., as - * indicated in the individual method specifications. A subclass can - * control the order elements are visited by overriding the - * visitXyz methods. Note that clients of a scanner - * may get the desired behavior be invoking {@code v.scan(e, p)} rather - * than {@code v.visit(e, p)} on the root objects of interest. + * class scan their component elements by calling {@link + * #scan(Element, P) scan} on their {@linkplain + * Element#getEnclosedElements enclosed elements}, {@linkplain + * ExecutableElement#getParameters parameters}, etc., as indicated in + * the individual method specifications. A subclass can control the + * order elements are visited by overriding the + * visitXyz methods. Note that clients of a + * scanner may get the desired behavior by invoking {@code v.scan(e, + * p)} rather than {@code v.visit(e, p)} on the root objects of + * interest. * *

    When a subclass overrides a visitXyz method, the * new method can cause the enclosed elements to be scanned in the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java index e79af27dacf617cd5b8f3ce723153b13bc201c68..73e286cea55602ce24449f9edb40d397f9d5c855 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, 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,14 +35,16 @@ import static javax.lang.model.SourceVersion.*; * A scanning visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_7 RELEASE_7} * source version. The visitXyz methods in this - * class scan their component elements by calling {@code scan} on - * their {@linkplain Element#getEnclosedElements enclosed elements}, - * {@linkplain ExecutableElement#getParameters parameters}, etc., as - * indicated in the individual method specifications. A subclass can - * control the order elements are visited by overriding the - * visitXyz methods. Note that clients of a scanner - * may get the desired behavior be invoking {@code v.scan(e, p)} rather - * than {@code v.visit(e, p)} on the root objects of interest. + * class scan their component elements by calling {@link + * ElementScanner6#scan(Element, Object) scan} on their {@linkplain + * Element#getEnclosedElements enclosed elements}, {@linkplain + * ExecutableElement#getParameters parameters}, etc., as indicated in + * the individual method specifications. A subclass can control the + * order elements are visited by overriding the + * visitXyz methods. Note that clients of a + * scanner may get the desired behavior by invoking {@code v.scan(e, + * p)} rather than {@code v.visit(e, p)} on the root objects of + * interest. * *

    When a subclass overrides a visitXyz method, the * new method can cause the enclosed elements to be scanned in the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner8.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner8.java index 229ab1a512ce12ae8c426ec94122d01568140b66..db3ee069d4b78f785febf3eae62f761e442fa0c9 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner8.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,14 +35,16 @@ import static javax.lang.model.SourceVersion.*; * A scanning visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_8 RELEASE_8} * source version. The visitXyz methods in this - * class scan their component elements by calling {@code scan} on - * their {@linkplain Element#getEnclosedElements enclosed elements}, - * {@linkplain ExecutableElement#getParameters parameters}, etc., as - * indicated in the individual method specifications. A subclass can - * control the order elements are visited by overriding the - * visitXyz methods. Note that clients of a scanner - * may get the desired behavior be invoking {@code v.scan(e, p)} rather - * than {@code v.visit(e, p)} on the root objects of interest. + * class scan their component elements by calling {@link + * ElementScanner6#scan(Element, Object) scan} on their {@linkplain + * Element#getEnclosedElements enclosed elements}, {@linkplain + * ExecutableElement#getParameters parameters}, etc., as indicated in + * the individual method specifications. A subclass can control the + * order elements are visited by overriding the + * visitXyz methods. Note that clients of a + * scanner may get the desired behavior by invoking {@code v.scan(e, + * p)} rather than {@code v.visit(e, p)} on the root objects of + * interest. * *

    When a subclass overrides a visitXyz method, the * new method can cause the enclosed elements to be scanned in the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java index b36235afd2a0dff8bf38c893303e3e7dd7ed9da1..3ee290d70cf975535546e773895a6e74339f2d23 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,16 @@ import static javax.lang.model.SourceVersion.*; * appropriate for source versions {@link SourceVersion#RELEASE_9 * RELEASE_9} through {@link SourceVersion#RELEASE_14 RELEASE_14}. * - * The visitXyz methods in this - * class scan their component elements by calling {@code scan} on - * their {@linkplain Element#getEnclosedElements enclosed elements}, - * {@linkplain ExecutableElement#getParameters parameters}, etc., as - * indicated in the individual method specifications. A subclass can - * control the order elements are visited by overriding the - * visitXyz methods. Note that clients of a scanner - * may get the desired behavior be invoking {@code v.scan(e, p)} rather - * than {@code v.visit(e, p)} on the root objects of interest. + * The visitXyz methods in this class scan their + * component elements by calling {@link ElementScanner6#scan(Element, + * Object) scan} on their {@linkplain Element#getEnclosedElements + * enclosed elements}, {@linkplain ExecutableElement#getParameters + * parameters}, etc., as indicated in the individual method + * specifications. A subclass can control the order elements are + * visited by overriding the visitXyz methods. + * Note that clients of a scanner may get the desired behavior by + * invoking {@code v.scan(e, p)} rather than {@code v.visit(e, p)} on + * the root objects of interest. * *

    When a subclass overrides a visitXyz method, the * new method can cause the enclosed elements to be scanned in the 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/resources/aqua_de.properties b/src/java.desktop/macosx/classes/com/apple/laf/resources/aqua_de.properties index 83105561c305a2345652bb9064ed200a247984ab..f4cb1f4d2b48a8e4f47e59a16d1a32a73a55d625 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/resources/aqua_de.properties +++ b/src/java.desktop/macosx/classes/com/apple/laf/resources/aqua_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # 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 @@ FileChooser.fileSizeGigaBytes={0} GB FileChooser.saveTitle.textAndMnemonic=Speichern FileChooser.openTitle.textAndMnemonic=\u00D6ffnen FileChooser.newFolderExistsError.textAndMnemonic=Dieser Name ist bereits vergeben -FileChooser.chooseButton.textAndMnemonic=W\u00E4hlen +FileChooser.chooseButton.textAndMnemonic=Ausw\u00E4hlen FileChooser.newFolderButton.textAndMnemonic=Neuer Ordner FileChooser.newFolderTitle.textAndMnemonic=Neuer Ordner diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 1796f5f3005b36d97f06f44b9fe8d823b73f0680..7f1528e84fdc99ef1177effab798a74e5fc88eae 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,7 @@ import java.awt.peer.KeyboardFocusManagerPeer; import java.awt.peer.WindowPeer; import java.util.List; +import java.util.Objects; import javax.swing.JComponent; import sun.awt.AWTAccessor; @@ -281,6 +282,16 @@ public class LWWindowPeer super.disposeImpl(); } + @Override + public void setBackground(final Color c) { + Color oldBg = getBackground(); + if (Objects.equals(oldBg, c)) { + return; + } + super.setBackground(c); + updateOpaque(); + } + @Override protected void setVisibleImpl(final boolean visible) { if (!visible && warningWindow != null) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index f338f25f05ed8d4d6a75582b7e4aa60b93ed06cf..efc6968150bbdfb2fca12c50d4904213dbd6535e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -28,6 +28,7 @@ package sun.lwawt.macosx; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.IllegalComponentStateException; import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Window; @@ -469,7 +470,16 @@ class CAccessibility implements PropertyChangeListener { public static Accessible accessibilityHitTest(final Container parent, final float hitPointX, final float hitPointY) { return invokeAndWait(new Callable() { public Accessible call() throws Exception { - final Point p = parent.getLocationOnScreen(); + if (parent == null) { + return null; + } + + final Point p; + try { + p = parent.getLocationOnScreen(); + } catch (IllegalComponentStateException ice) { + return null; + } // Make it into local coords final Point localPoint = new Point((int)(hitPointX - p.getX()), (int)(hitPointY - p.getY())); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index 6a8076ee118130661daad5284cfadea07e76d7dc..8570ecaa97a8e10187eeccef09437921ad1f00fb 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import sun.awt.CGraphicsDevice; import sun.java2d.SurfaceData; import sun.java2d.metal.MTLLayer; import sun.java2d.opengl.CGLLayer; -import sun.lwawt.macosx.CFLayer; import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; import sun.util.logging.PlatformLogger; @@ -199,7 +198,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { /* * The method could not be implemented due to CALayer restrictions. - * The exeption enforce clients not to use it. + * The exception enforces clients not to use it. */ @Override public boolean isUnderMouse() { 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/com/sun/accessibility/internal/resources/accessibility_de.properties b/src/java.desktop/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties index 78c95becd1ad681a60dcd3065f525ca74b77b05f..a58b033abe3afbbe3e2b3fa33a3f30640b6fce6a 100644 --- a/src/java.desktop/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties +++ b/src/java.desktop/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties @@ -91,7 +91,7 @@ window=Fenster # accessible relations # labelFor=Label f\u00FCr -labeledBy=beschriftet von +labeledBy=gelabelt von memberOf=Mitglied von controlledBy=controlledBy controllerFor=controllerFor diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 2e1c2db03ca84d64cdaa2c2abb00dabffeb1edb9..81baefe81559d04c9bf3a150999c4c7d498356c3 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -254,11 +254,11 @@ public class BMPImageReader extends ImageReader implements BMPConstants { /** * Process the image header. * - * @exception IllegalStateException if source stream is not set. + * @throws IllegalStateException if source stream is not set. * - * @exception IOException if image stream is corrupted. + * @throws IOException if image stream is corrupted. * - * @exception IllegalArgumentException if the image stream does not contain + * @throws IllegalArgumentException if the image stream does not contain * a BMP image, or if a sample model instance to describe the * image can not be created. */ diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java index b6f73efc712c4dfb455e73dbbd447fdbee32c96d..a62008dfbd46cd6f8ef810e7d97bf2565e8fc48e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java @@ -38,7 +38,7 @@ public class BogusColorSpace extends ColorSpace { * * @param numComponents The number of components in the * {@code ColorSpace}. - * @exception IllegalArgumentException if {@code numComponents} + * @throws IllegalArgumentException if {@code numComponents} * is less than 1. */ private static int getType(int numComponents) { @@ -66,7 +66,7 @@ public class BogusColorSpace extends ColorSpace { * * @param numComponents The number of components in the * {@code ColorSpace}. - * @exception IllegalArgumentException if {@code numComponents} + * @throws IllegalArgumentException if {@code numComponents} * is less than 1. */ public BogusColorSpace(int numComponents) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWCompressor.java index 0177848ad80f755058df0f81ba1f8bf7c204b5f3..52f66f5eafaaed481a6eee2405cbfa1857b61f59 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWCompressor.java @@ -65,7 +65,7 @@ public class LZWCompressor { * @param out destination for compressed data * @param codeSize the initial code size for the LZW compressor * @param TIFF flag indicating that TIFF lzw fudge needs to be applied - * @exception IOException if underlying output stream error + * @throws IOException if underlying output stream error **/ public LZWCompressor(ImageOutputStream out, int codeSize, boolean TIFF) throws IOException @@ -90,7 +90,7 @@ public class LZWCompressor { /** * @param buf data to be compressed to output stream - * @exception IOException if underlying output stream error + * @throws IOException if underlying output stream error **/ public void compress(byte[] buf, int offset, int length) throws IOException @@ -129,7 +129,7 @@ public class LZWCompressor { * Indicate to compressor that no more data to go so write out * any remaining buffered data. * - * @exception IOException if underlying output stream error + * @throws IOException if underlying output stream error */ public void flush() throws IOException { if (prefix != -1) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java index b4541d5c66294cbd94d949d4dc0d1686a97c3352..00d2dde0e889becd71f3a04de759e6043adb3a12 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java @@ -77,10 +77,10 @@ public class PaletteBuilder { * Result image then is an approximation constructed by octree * quantization method. * - * @exception IllegalArgumentException if {@code src} is + * @throws IllegalArgumentException if {@code src} is * {@code null}. * - * @exception UnsupportedOperationException if implemented method + * @throws UnsupportedOperationException if implemented method * is unable to create approximation of {@code src} * and {@code canCreatePalette} returns {@code false}. * @@ -98,10 +98,10 @@ public class PaletteBuilder { * {@code img}. If number of colors in the given image exceeds * maximum palette size closest colors would be merged. * - * @exception IllegalArgumentException if {@code img} is + * @throws IllegalArgumentException if {@code img} is * {@code null}. * - * @exception UnsupportedOperationException if implemented method + * @throws UnsupportedOperationException if implemented method * is unable to create approximation of {@code img} * and {@code canCreatePalette} returns {@code false}. * @@ -124,7 +124,7 @@ public class PaletteBuilder { * @return {@code true} if the {@code PaletteBuilder} * is likely to be able to create palette for this image type. * - * @exception IllegalArgumentException if {@code type} + * @throws IllegalArgumentException if {@code type} * is {@code null}. */ public static boolean canCreatePalette(ImageTypeSpecifier type) { @@ -144,7 +144,7 @@ public class PaletteBuilder { * @return {@code true} if the {@code PaletteBuilder} * is likely to be able to create palette for this image type. * - * @exception IllegalArgumentException if {@code image} + * @throws IllegalArgumentException if {@code image} * is {@code null}. */ public static boolean canCreatePalette(RenderedImage image) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java index 75586561598ad0cb7048647f6565df7867036640..a5c283e6c9c627d33c9f3fce29f18cd8a9877097 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java @@ -63,7 +63,7 @@ public final class SimpleCMYKColorSpace extends ColorSpace { } public int hashCode() { - return theInstance.hashCode(); + return System.identityHashCode(theInstance); } public float[] toRGB(float[] colorvalue) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index a7edf73cb80b6cbb4e518ea9150dac18ac62dedc..e18397774808595f7aaf5712b9ae161e743ebd89 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -35,6 +35,7 @@ import javax.imageio.stream.ImageInputStream; import javax.imageio.plugins.jpeg.JPEGImageReadParam; import javax.imageio.plugins.jpeg.JPEGQTable; import javax.imageio.plugins.jpeg.JPEGHuffmanTable; +import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; import java.awt.Point; import java.awt.Rectangle; @@ -164,6 +165,12 @@ public class JPEGImageReader extends ImageReader { /** If we need to post-convert in Java, convert with this op */ private ColorConvertOp convert = null; + /** If reading CMYK as an Image, flip the bytes */ + private boolean invertCMYK = false; + + /** Whether to read as a raster */ + private boolean readAsRaster = false; + /** The image we are going to fill */ private BufferedImage image = null; @@ -487,9 +494,9 @@ public class JPEGImageReader extends ImageReader { /** * Sets the input stream to the start of the requested image. *

    -     * @exception IllegalStateException if the input source has not been
    +     * @throws IllegalStateException if the input source has not been
          * set.
    -     * @exception IndexOutOfBoundsException if the supplied index is
    +     * @throws IndexOutOfBoundsException if the supplied index is
          * out of bounds.
          * 
    */ @@ -938,6 +945,32 @@ public class JPEGImageReader extends ImageReader { ArrayList list = new ArrayList(1); switch (colorSpaceCode) { + case JPEG.JCS_YCCK: + case JPEG.JCS_CMYK: + // There's no standard CMYK ColorSpace in JDK so raw.getType() + // will return null so skip that. + // And we can't add RGB because the number of bands is different. + // So need to create our own special that is 4 channels and uses + // the iccCS ColorSpace based on profile data in the image, and + // if there is none, on the internal CMYKColorSpace class + if (iccCS == null) { + iccCS = SimpleCMYKColorSpace.getInstance(); + } + if (iccCS != null) { + list.add(new ImageTypeProducer(colorSpaceCode) { + @Override + protected ImageTypeSpecifier produce() { + int [] bands = {0, 1, 2, 3}; + return ImageTypeSpecifier.createInterleaved + (iccCS, + bands, + DataBuffer.TYPE_BYTE, + false, + false); + } + }); + } + break; case JPEG.JCS_GRAYSCALE: list.add(raw); list.add(getImageType(JPEG.JCS_RGB)); @@ -1019,6 +1052,8 @@ public class JPEGImageReader extends ImageReader { int csType = cs.getType(); convert = null; switch (outColorSpaceCode) { + case JPEG.JCS_CMYK: // Its CMYK in the file + break; case JPEG.JCS_GRAYSCALE: // Its gray in the file if (csType == ColorSpace.TYPE_RGB) { // We want RGB // IJG can do this for us more efficiently @@ -1144,6 +1179,8 @@ public class JPEGImageReader extends ImageReader { private Raster readInternal(int imageIndex, ImageReadParam param, boolean wantRaster) throws IOException { + + readAsRaster = wantRaster; readHeader(imageIndex, false); WritableRaster imRas = null; @@ -1186,6 +1223,16 @@ public class JPEGImageReader extends ImageReader { image = null; } + // Adobe seems to have decided that the bytes in CMYK JPEGs + // should be stored inverted. So we need some extra logic to + // flip them in that case. Don't flip for the raster case + // so code that is reading these as rasters today won't + // see a change in behaviour. + invertCMYK = + (!wantRaster && + ((colorSpaceCode == JPEG.JCS_YCCK) || + (colorSpaceCode == JPEG.JCS_CMYK))); + // Create an intermediate 1-line Raster that will hold the decoded, // subsampled, clipped, band-selected image data in a single // byte-interleaved buffer. The above transformations @@ -1363,6 +1410,21 @@ public class JPEGImageReader extends ImageReader { * After the copy, we notify update listeners. */ private void acceptPixels(int y, boolean progressive) { + + /* + * CMYK JPEGs seems to be universally inverted at the byte level. + * Fix this here before storing. + * For "compatibility" don't do this if the target is a raster. + * Need to do this here in case the application is listening + * for line-by-line updates to the image. + */ + if (invertCMYK) { + byte[] data = ((DataBufferByte)raster.getDataBuffer()).getData(); + for (int i = 0, len = data.length; i < len; i++) { + data[i] = (byte)(0x0ff - (data[i] & 0xff)); + } + } + if (convert != null) { convert.filter(raster, raster); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index 31acae628a14e895a17c426e471a0c1a0783b725..fcce8f60495da319eb438bcbb57dacf3caae5966 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -131,6 +131,7 @@ public class JPEGImageWriter extends ImageWriter { private int newAdobeTransform = JPEG.ADOBE_IMPOSSIBLE; // Change if needed private boolean writeDefaultJFIF = false; private boolean writeAdobe = false; + private boolean invertCMYK = false; private JPEGMetadata metadata = null; private boolean sequencePrepared = false; @@ -654,6 +655,7 @@ public class JPEGImageWriter extends ImageWriter { newAdobeTransform = JPEG.ADOBE_IMPOSSIBLE; // Change if needed writeDefaultJFIF = false; writeAdobe = false; + invertCMYK = false; // By default we'll do no conversion: int inCsType = JPEG.JCS_UNKNOWN; @@ -807,6 +809,14 @@ public class JPEGImageWriter extends ImageWriter { } } break; + case ColorSpace.TYPE_CMYK: + outCsType = JPEG.JCS_CMYK; + if (jfif != null) { + ignoreJFIF = true; + warningOccurred + (WARNING_IMAGE_METADATA_JFIF_MISMATCH); + } + break; } } } // else no dest, metadata, not an image. Defaults ok @@ -1013,6 +1023,11 @@ public class JPEGImageWriter extends ImageWriter { System.out.println("outCsType: " + outCsType); } + invertCMYK = + (!rasterOnly && + ((outCsType == JPEG.JCS_YCCK) || + (outCsType == JPEG.JCS_CMYK))); + // Note that getData disables acceleration on buffer, but it is // just a 1-line intermediate data transfer buffer that does not // affect the acceleration of the source image. @@ -1721,6 +1736,12 @@ public class JPEGImageWriter extends ImageWriter { srcBands); } raster.setRect(sourceLine); + if (invertCMYK) { + byte[] data = ((DataBufferByte)raster.getDataBuffer()).getData(); + for (int i = 0, len = data.length; i < len; i++) { + data[i] = (byte)(0x0ff - (data[i] & 0xff)); + } + } if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines cbLock.lock(); try { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index ce6f771ecdceb539a4bc27562fbda1167cb429d0..27707613f76eeeb81390d3e662af71f83ec699f9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -322,7 +322,7 @@ final class PNGImageWriteParam extends ImageWriteParam { *

    The default implementation resets the compression quality * to 0.5F. * - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * MODE_EXPLICIT. */ @Override diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java index 4516ce0ad82e391319cb46d7332112d2892b5c26..bd7eb568fd88e28eb83142073df105e253918982 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java @@ -2373,7 +2373,7 @@ public abstract class TIFFDecompressor { * and instead override the {@code decodeRaw} and/or * {@code getRawImageType} methods. * - * @exception IOException if an error occurs in + * @throws IOException if an error occurs in * {@code decodeRaw}. */ public void decode() throws IOException { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java b/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java index c8d9cd8d2db33166e9e4810e450803baa87d6bd2..6ef0695c70d0e35e81bb11fb5d0033af2744d800 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java @@ -172,7 +172,7 @@ public final class AiffFileReader extends SunFileReader { * Extended precision IEEE floating-point conversion routine. * @argument DataInputStream * @return double - * @exception IOException + * @throws IOException */ private double read_ieee_extended(DataInputStream dis) throws IOException { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java b/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java index d384bf279c4153432e6bd759eb0614574184c3c3..3738a557aef67617adf9e471fb5d813f07af4675 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java @@ -392,7 +392,7 @@ public final class AiffFileWriter extends SunFileWriter { * Extended precision IEEE floating-point conversion routine. * @argument DataOutputStream * @argument double - * @exception IOException + * @throws IOException */ private void write_ieee_extended(DataOutputStream dos, float f) throws IOException { /* The special cases NaN, Infinity and Zero are ignored, since diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java b/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java index ef995f812948d7353198dab174ba331ff322c1f1..89323cfe3c3bb5d2ca19831be20d088e2922afef 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java @@ -164,7 +164,7 @@ abstract class SunFileReader extends AudioFileReader { * Protected helper method to read 64 bits and changing the order of * each bytes. * @return 32 bits swapped value. - * @exception IOException + * @throws IOException */ final int rllong(DataInputStream dis) throws IOException { @@ -206,7 +206,7 @@ abstract class SunFileReader extends AudioFileReader { * rlshort * Protected helper method to read 16 bits value. Swap high with low byte. * @return the swapped value. - * @exception IOException + * @throws IOException */ final short rlshort(DataInputStream dis) throws IOException { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java b/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java index 1d54bcfe91c0c60294c037f43c1827b2a40071ed..8e85f1e743f87712bdc2741ee23c2060b6756e90 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java @@ -70,7 +70,7 @@ abstract class SunFileWriter extends AudioFileWriter { * Protected helper method to read 64 bits and changing the order of * each bytes. * @return 32 bits swapped value. - * @exception IOException + * @throws IOException */ final int rllong(DataInputStream dis) throws IOException { @@ -112,7 +112,7 @@ abstract class SunFileWriter extends AudioFileWriter { * rlshort * Protected helper method to read 16 bits value. Swap high with low byte. * @return the swapped value. - * @exception IOException + * @throws IOException */ final short rlshort(DataInputStream dis) throws IOException { 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..0265142aee3e9a349bfdf9d366f21e174c78829c 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() @@ -357,9 +357,9 @@ public abstract class GraphicsEnvironment { } /** - * Indicates a preference for proportional over non-proportional (e.g. - * dual-spaced CJK fonts) fonts in the mapping of logical fonts to - * physical fonts. If the default mapping contains fonts for which + * Indicates a preference for proportional over non-proportional (for + * example dual-spaced CJK fonts) fonts in the mapping of logical fonts + * to physical fonts. If the default mapping contains fonts for which * proportional and non-proportional variants exist, then calling * this method indicates the mapping should use a proportional variant. *

    @@ -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/GridBagLayoutInfo.java b/src/java.desktop/share/classes/java/awt/GridBagLayoutInfo.java index 64a283546c52aa374323b19a4ef5cc41687f153f..1a4ed2942c505ec03709717fbfaba12a6d39652a 100644 --- a/src/java.desktop/share/classes/java/awt/GridBagLayoutInfo.java +++ b/src/java.desktop/share/classes/java/awt/GridBagLayoutInfo.java @@ -36,7 +36,7 @@ import java.io.Serial; * @see java.awt.GridBagConstraints * @since 1.6 */ -public class GridBagLayoutInfo implements java.io.Serializable { +public final class GridBagLayoutInfo implements java.io.Serializable { /** * Use serialVersionUID from JDK 1.6 for interoperability. 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/PointerInfo.java b/src/java.desktop/share/classes/java/awt/PointerInfo.java index 9b51d6ead3670126b10d85a21c72099e53813bd3..7d74d884cf0d36a604e31167f17b2fd2c6550d50 100644 --- a/src/java.desktop/share/classes/java/awt/PointerInfo.java +++ b/src/java.desktop/share/classes/java/awt/PointerInfo.java @@ -41,7 +41,7 @@ package java.awt; * @author Roman Poborchiy * @since 1.5 */ -public class PointerInfo { +public final class PointerInfo { private final GraphicsDevice device; private final Point location; 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/ScrollPaneAdjustable.java b/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java index d2b3eebdebb3b4a5cec1e56bac1bfd9c39dea54c..d8d70fd2476d565e494bc0927c38a1d8f986e0a6 100644 --- a/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java +++ b/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java @@ -40,7 +40,7 @@ import sun.awt.AWTAccessor; * * @since 1.4 */ -public class ScrollPaneAdjustable implements Adjustable, Serializable { +public final class ScrollPaneAdjustable implements Adjustable, Serializable { /** * The {@code ScrollPane} this object is a scrollbar of. 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..fcf37543e5b524e349f249ab15a5c75cc462685c 100644 --- a/src/java.desktop/share/classes/java/awt/TextArea.java +++ b/src/java.desktop/share/classes/java/awt/TextArea.java @@ -55,7 +55,7 @@ import javax.accessibility.AccessibleStateSet; * @author Sami Shaio * @since 1.0 */ -public class TextArea extends TextComponent { +public non-sealed class TextArea extends TextComponent { /** * The number of rows in the {@code TextArea}. @@ -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..b1ccc9bd87a79b991ccc4ce3c3b32598ba4835fe 100644 --- a/src/java.desktop/share/classes/java/awt/TextComponent.java +++ b/src/java.desktop/share/classes/java/awt/TextComponent.java @@ -67,7 +67,9 @@ import sun.awt.InputMethodSupport; * @author Arthur van Hoff * @since 1.0 */ -public class TextComponent extends Component implements Accessible { +public sealed class TextComponent extends Component implements Accessible + permits TextArea, + TextField { /** * The value of the text. @@ -137,7 +139,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 +513,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 +647,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..0d74f238a87c8495cde6df75489e1db164c2610f 100644 --- a/src/java.desktop/share/classes/java/awt/TextField.java +++ b/src/java.desktop/share/classes/java/awt/TextField.java @@ -99,7 +99,7 @@ import javax.accessibility.AccessibleStateSet; * @see java.awt.TextField#addActionListener * @since 1.0 */ -public class TextField extends TextComponent { +public non-sealed class TextField extends TextComponent { /** * The number of columns in the text field. @@ -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/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index ff8e0745e19d77653bf0551261c300cc743e0703..278e53ae10a0674e5099bd89b4ab86f24e441baf 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -83,7 +83,9 @@ import sun.java2d.cmm.ProfileDeferralInfo; * * @see ICC_ColorSpace */ -public class ICC_Profile implements Serializable { +public sealed class ICC_Profile implements Serializable + permits ICC_ProfileGray, + ICC_ProfileRGB { /** * Use serialVersionUID from JDK 1.2 for interoperability. diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java index 5df533ee47cb28aad201bf19b3ef9ae95efc75e7..b248e996c81c12a79b80114ed46ad03b7fc618ea 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java @@ -65,7 +65,7 @@ import sun.java2d.cmm.ProfileDeferralInfo; * The inverse transform is done by converting the PCS Y components to device * Gray via the inverse of the grayTRC. */ -public class ICC_ProfileGray extends ICC_Profile { +public final class ICC_ProfileGray extends ICC_Profile { /** * Use serialVersionUID from JDK 1.2 for interoperability. diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java index 56c3e8a848cea8a32c4784261187af22a9b1919a..b3683a941ee9ca94b4c5d48e4cd8812e6a4066f4 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java @@ -80,7 +80,7 @@ import sun.java2d.cmm.ProfileDeferralInfo; * RGB components through the inverse of the above 3x3 matrix, and then * converting linear RGB to device RGB through inverses of the TRCs. */ -public class ICC_ProfileRGB extends ICC_Profile { +public final class ICC_ProfileRGB extends ICC_Profile { /** * Use serialVersionUID from JDK 1.2 for interoperability. diff --git a/src/java.desktop/share/classes/java/awt/desktop/AppEvent.java b/src/java.desktop/share/classes/java/awt/desktop/AppEvent.java index f2291b4c37b141bdba97cc7a84cbccde8a1aa57d..aeb1a83ea76f89cbcf13b0f0c62820cb15a7404f 100644 --- a/src/java.desktop/share/classes/java/awt/desktop/AppEvent.java +++ b/src/java.desktop/share/classes/java/awt/desktop/AppEvent.java @@ -37,7 +37,18 @@ import java.util.EventObject; * * @since 9 */ -public class AppEvent extends EventObject { +public sealed class AppEvent extends EventObject + permits AboutEvent, + AppForegroundEvent, + AppHiddenEvent, + AppReopenedEvent, + FilesEvent, + OpenURIEvent, + PreferencesEvent, + QuitEvent, + ScreenSleepEvent, + SystemSleepEvent, + UserSessionEvent { /** * Use serialVersionUID from JDK 9 for interoperability. diff --git a/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java b/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java index b53beb36230b0b864bf4eb15528977779bfd89da..9f07814f5ac90c29822b7d9dee9784bb9e48e255 100644 --- a/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java +++ b/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java @@ -38,7 +38,9 @@ import java.util.List; * * @since 9 */ -public class FilesEvent extends AppEvent { +public sealed class FilesEvent extends AppEvent + permits OpenFilesEvent, + PrintFilesEvent { /** * Use serialVersionUID from JDK 9 for interoperability. 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/dnd/DropTargetContext.java b/src/java.desktop/share/classes/java/awt/dnd/DropTargetContext.java index 8eac26a5fd267d77a3663c9f7d6ce0556e44b94c..ea31203b98823ffd47c33fd930a6b1b54ba43785 100644 --- a/src/java.desktop/share/classes/java/awt/dnd/DropTargetContext.java +++ b/src/java.desktop/share/classes/java/awt/dnd/DropTargetContext.java @@ -53,7 +53,7 @@ import sun.awt.AWTAccessor.DropTargetContextAccessor; * @since 1.2 */ -public class DropTargetContext implements Serializable { +public final class DropTargetContext implements Serializable { /** * Use serialVersionUID from JDK 1.4 for interoperability. diff --git a/src/java.desktop/share/classes/java/awt/event/InputEvent.java b/src/java.desktop/share/classes/java/awt/event/InputEvent.java index a4f310dd08cc70681591a9c89f7ddb1e49db9a13..60d3b4d812d9b88d73a743a20b21582049a140ef 100644 --- a/src/java.desktop/share/classes/java/awt/event/InputEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/InputEvent.java @@ -57,7 +57,9 @@ import sun.util.logging.PlatformLogger; * * @since 1.1 */ -public abstract class InputEvent extends ComponentEvent { +public abstract sealed class InputEvent extends ComponentEvent + permits KeyEvent, + MouseEvent { private static final PlatformLogger logger = PlatformLogger.getLogger("java.awt.event.InputEvent"); diff --git a/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java b/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java index 94cfcc0bf402bde52ba8d21a46033b471197192c..12ad1a0317130ed2c13916089442167a062adad1 100644 --- a/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java @@ -436,7 +436,7 @@ public class InputMethodEvent extends AWTEvent { * belongs to. * * @param source the source of the event - * @exception IllegalArgumentException if source is null. + * @throws IllegalArgumentException if source is null. * @return most recent event time in the {@code EventQueue} */ private static long getMostRecentEventTimeForSource(Object source) { diff --git a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java index 21bf7ec17162b7f82ee974aa0d18070536243dfe..37f386c8793ce731e0cb27393c235fe77af205e2 100644 --- a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java @@ -151,7 +151,7 @@ import sun.awt.AWTAccessor; * * @since 1.1 */ -public class KeyEvent extends InputEvent { +public non-sealed class KeyEvent extends InputEvent { /** * Stores the state of native event dispatching system diff --git a/src/java.desktop/share/classes/java/awt/event/MouseEvent.java b/src/java.desktop/share/classes/java/awt/event/MouseEvent.java index f681c906fa050bd3520e446f98ffee7b13e0e0d6..42b1fb9c39cc902957d8f740e5ad117641372424 100644 --- a/src/java.desktop/share/classes/java/awt/event/MouseEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/MouseEvent.java @@ -189,7 +189,7 @@ import sun.awt.SunToolkit; * * @since 1.1 */ -public class MouseEvent extends InputEvent { +public non-sealed class MouseEvent extends InputEvent { /** * The first number in the range of ids used for mouse events. diff --git a/src/java.desktop/share/classes/java/awt/font/TextLayout.java b/src/java.desktop/share/classes/java/awt/font/TextLayout.java index ddc5199b8432196a97ad7454e98ed56baf34fbbd..352d3c81df247f84dcb711f1a7fa71eaf62e7671 100644 --- a/src/java.desktop/share/classes/java/awt/font/TextLayout.java +++ b/src/java.desktop/share/classes/java/awt/font/TextLayout.java @@ -789,7 +789,7 @@ public final class TextLayout implements Cloneable { * For best results, it should not be too different from the current * advance of the line. * @return a {@code TextLayout} justified to the specified width. - * @exception Error if this layout has already been justified, an Error is + * @throws Error if this layout has already been justified, an Error is * thrown. */ public TextLayout getJustifiedLayout(float justificationWidth) { diff --git a/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java b/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java index 44324e2d3b9a2f1a731788a140943732f5e14940..7f6fc7c34f986880d3cb2112076c43211cd33848 100644 --- a/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java +++ b/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java @@ -2667,7 +2667,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @return a new {@code AffineTransform} object representing the * inverse transformation. * @see #getDeterminant - * @exception NoninvertibleTransformException + * @throws NoninvertibleTransformException * if the matrix cannot be inverted. * @since 1.2 */ @@ -2762,7 +2762,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * transform has no inverse, in which case an exception will be * thrown if the {@code invert} method is called. * @see #getDeterminant - * @exception NoninvertibleTransformException + * @throws NoninvertibleTransformException * if the matrix cannot be inverted. * @since 1.6 */ @@ -3464,7 +3464,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @param ptDst the resulting transformed point * @return {@code ptDst}, which contains the result of the * inverse transform. - * @exception NoninvertibleTransformException if the matrix cannot be + * @throws NoninvertibleTransformException if the matrix cannot be * inverted. * @since 1.2 */ @@ -3550,7 +3550,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @param dstOff the offset to the location of the first * transformed point that is stored in the destination array * @param numPts the number of point objects to be transformed - * @exception NoninvertibleTransformException if the matrix cannot be + * @throws NoninvertibleTransformException if the matrix cannot be * inverted. * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/CubicCurve2D.java b/src/java.desktop/share/classes/java/awt/geom/CubicCurve2D.java index 76d366c0ec66e6eb0c102f22ffb0a805e62dc72e..cf33fb30438a8367ef5b41d75f7b5b18c97cc522 100644 --- a/src/java.desktop/share/classes/java/awt/geom/CubicCurve2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/CubicCurve2D.java @@ -1564,7 +1564,7 @@ public abstract class CubicCurve2D implements Shape, Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/Dimension2D.java b/src/java.desktop/share/classes/java/awt/geom/Dimension2D.java index 180d96a3840ff976f1211cbba91c033d6bdf99b9..0a2015b15a999a15127ca689d263d9b57231aece 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Dimension2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Dimension2D.java @@ -99,7 +99,7 @@ public abstract class Dimension2D implements Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/FlatteningPathIterator.java b/src/java.desktop/share/classes/java/awt/geom/FlatteningPathIterator.java index 40159f2db5ff4aee33cdceefc1304c3713480a67..123e6d60b928f7067d4d2d9870a29549f210ac00 100644 --- a/src/java.desktop/share/classes/java/awt/geom/FlatteningPathIterator.java +++ b/src/java.desktop/share/classes/java/awt/geom/FlatteningPathIterator.java @@ -109,7 +109,7 @@ public class FlatteningPathIterator implements PathIterator { * control points and the flattened curve * @param limit the maximum number of recursive subdivisions * allowed for any curved segment - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code flatness} or {@code limit} * is less than zero */ @@ -336,7 +336,7 @@ public class FlatteningPathIterator implements PathIterator { * @param coords an array that holds the data returned from * this method * @return the path segment type of the current path segment. - * @exception NoSuchElementException if there + * @throws NoSuchElementException if there * are no more elements in the flattening path to be * returned. * @see PathIterator#SEG_MOVETO @@ -371,7 +371,7 @@ public class FlatteningPathIterator implements PathIterator { * @param coords an array that holds the data returned from * this method * @return the path segment type of the current path segment. - * @exception NoSuchElementException if there + * @throws NoSuchElementException if there * are no more elements in the flattening path to be * returned. * @see PathIterator#SEG_MOVETO diff --git a/src/java.desktop/share/classes/java/awt/geom/Line2D.java b/src/java.desktop/share/classes/java/awt/geom/Line2D.java index 3d79e44dfee1caf027f3a0c615b3ef7a7a5a0117..305b51942d9949cacc245b79c46d71fa0b49a72e 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Line2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Line2D.java @@ -1111,7 +1111,7 @@ public abstract class Line2D implements Shape, Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/Path2D.java b/src/java.desktop/share/classes/java/awt/geom/Path2D.java index 6168664452baf40d773e78898ec13a75576f7647..e8d752c2bf31de7eed955151f2349676c3c160a6 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Path2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Path2D.java @@ -70,7 +70,9 @@ import sun.awt.geom.Curve; * @author Jim Graham * @since 1.6 */ -public abstract class Path2D implements Shape, Cloneable { +public abstract sealed class Path2D implements Shape, Cloneable + permits Path2D.Double, + Path2D.Float { /** * An even-odd winding rule for determining the interior of * a path. @@ -191,7 +193,7 @@ public abstract class Path2D implements Shape, Cloneable { * * @since 1.6 */ - public static class Float extends Path2D implements Serializable { + public static non-sealed class Float extends Path2D implements Serializable { transient float[] floatCoords; /** @@ -842,7 +844,7 @@ public abstract class Path2D implements Shape, Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.6 */ @@ -1093,7 +1095,7 @@ public abstract class Path2D implements Shape, Cloneable { * * @since 1.6 */ - public static class Double extends Path2D implements Serializable { + public static non-sealed class Double extends Path2D implements Serializable { transient double[] doubleCoords; /** @@ -1638,7 +1640,7 @@ public abstract class Path2D implements Shape, Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.6 */ @@ -2018,7 +2020,7 @@ public abstract class Path2D implements Shape, Cloneable { * * @param rule an integer representing the specified * winding rule - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code rule} is not either * {@link #WIND_EVEN_ODD} or * {@link #WIND_NON_ZERO} @@ -2530,7 +2532,7 @@ public abstract class Path2D implements Shape, Cloneable { * Creates a new object of the same class as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.6 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/Point2D.java b/src/java.desktop/share/classes/java/awt/geom/Point2D.java index bffb5594cfa0fe94d237150fecf291746ece1807..2b0a2aabef1002003b9dc0772d7a564186263819 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Point2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Point2D.java @@ -387,7 +387,7 @@ public abstract class Point2D implements Cloneable { * Creates a new object of the same class and with the * same contents as this object. * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/QuadCurve2D.java b/src/java.desktop/share/classes/java/awt/geom/QuadCurve2D.java index f7dce7ea8e3c9eab88ecd3bf76bf500aba1e43cd..6f4990df49c122a8faeb3ed9f8b5d8a3bb2aee3e 100644 --- a/src/java.desktop/share/classes/java/awt/geom/QuadCurve2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/QuadCurve2D.java @@ -1388,7 +1388,7 @@ public abstract class QuadCurve2D implements Shape, Cloneable { * as this object. * * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/geom/RectangularShape.java b/src/java.desktop/share/classes/java/awt/geom/RectangularShape.java index 892eb634559af6a9bee48b7d2fbbd139535760ef..d0b0792792e69cee55b596035c0fa5512a063d4b 100644 --- a/src/java.desktop/share/classes/java/awt/geom/RectangularShape.java +++ b/src/java.desktop/share/classes/java/awt/geom/RectangularShape.java @@ -382,7 +382,7 @@ public abstract class RectangularShape implements Shape, Cloneable { * Creates a new object of the same class and with the same * contents as this object. * @return a clone of this instance. - * @exception OutOfMemoryError if there is not enough memory. + * @throws OutOfMemoryError if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ diff --git a/src/java.desktop/share/classes/java/awt/im/InputContext.java b/src/java.desktop/share/classes/java/awt/im/InputContext.java index 2a73793df2b7c79af656e10d538a80f6278ab94a..5476d9e2518294c8a95502d6a658c48a027bbf62 100644 --- a/src/java.desktop/share/classes/java/awt/im/InputContext.java +++ b/src/java.desktop/share/classes/java/awt/im/InputContext.java @@ -140,7 +140,7 @@ public class InputContext { * @param locale The desired new locale. * @return true if the input method or keyboard layout that's active after * this call supports the desired locale. - * @exception NullPointerException if {@code locale} is null + * @throws NullPointerException if {@code locale} is null */ public boolean selectInputMethod(Locale locale) { // real implementation is in sun.awt.im.InputContext @@ -268,7 +268,7 @@ public class InputContext { * If no input method is available, then the event will never be consumed. * * @param event The event - * @exception NullPointerException if {@code event} is null + * @throws NullPointerException if {@code event} is null */ public void dispatchEvent(AWTEvent event) { // real implementation is in sun.awt.im.InputContext @@ -286,7 +286,7 @@ public class InputContext { * If no input methods are available, then this method has no effect. * * @param client Client component - * @exception NullPointerException if {@code client} is null + * @throws NullPointerException if {@code client} is null */ public void removeNotify(Component client) { // real implementation is in sun.awt.im.InputContext diff --git a/src/java.desktop/share/classes/java/awt/im/InputMethodHighlight.java b/src/java.desktop/share/classes/java/awt/im/InputMethodHighlight.java index 7fcf3c9549bdf8fdb54f6ed69bb9fa41734ef519..4b8d4d5c9ea9e94be2496d53adfb46db66628232 100644 --- a/src/java.desktop/share/classes/java/awt/im/InputMethodHighlight.java +++ b/src/java.desktop/share/classes/java/awt/im/InputMethodHighlight.java @@ -111,7 +111,7 @@ public class InputMethodHighlight { * @param state The conversion state for the text range - RAW_TEXT or CONVERTED_TEXT * @see InputMethodHighlight#RAW_TEXT * @see InputMethodHighlight#CONVERTED_TEXT - * @exception IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given + * @throws IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given */ public InputMethodHighlight(boolean selected, int state) { this(selected, state, 0, null); @@ -125,7 +125,7 @@ public class InputMethodHighlight { * @param variation The style variation for the text range * @see InputMethodHighlight#RAW_TEXT * @see InputMethodHighlight#CONVERTED_TEXT - * @exception IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given + * @throws IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given */ public InputMethodHighlight(boolean selected, int state, int variation) { this(selected, state, variation, null); @@ -140,7 +140,7 @@ public class InputMethodHighlight { * @param style the rendering style attributes for the text range, or null * @see InputMethodHighlight#RAW_TEXT * @see InputMethodHighlight#CONVERTED_TEXT - * @exception IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given + * @throws IllegalArgumentException if a state other than RAW_TEXT or CONVERTED_TEXT is given * @since 1.3 */ public InputMethodHighlight(boolean selected, int state, int variation, diff --git a/src/java.desktop/share/classes/java/awt/im/spi/InputMethod.java b/src/java.desktop/share/classes/java/awt/im/spi/InputMethod.java index 1174493cc580a83228bead35e75af1958664c7fc..c01987bbfeda39a419a5e3a3e8ea21efda6e2738 100644 --- a/src/java.desktop/share/classes/java/awt/im/spi/InputMethod.java +++ b/src/java.desktop/share/classes/java/awt/im/spi/InputMethod.java @@ -59,7 +59,7 @@ public interface InputMethod { * method. * * @param context the input method context for this input method - * @exception NullPointerException if {@code context} is null + * @throws NullPointerException if {@code context} is null */ public void setInputMethodContext(InputMethodContext context); @@ -80,7 +80,7 @@ public interface InputMethod { * * @param locale locale to input * @return whether the specified locale is supported - * @exception NullPointerException if {@code locale} is null + * @throws NullPointerException if {@code locale} is null */ public boolean setLocale(Locale locale); @@ -211,7 +211,7 @@ public interface InputMethod { * This method is called by {@link java.awt.im.InputContext#dispatchEvent InputContext.dispatchEvent}. * * @param event the event being dispatched to the input method - * @exception NullPointerException if {@code event} is null + * @throws NullPointerException if {@code event} is null */ public void dispatchEvent(AWTEvent event); diff --git a/src/java.desktop/share/classes/java/awt/im/spi/InputMethodContext.java b/src/java.desktop/share/classes/java/awt/im/spi/InputMethodContext.java index 09d44a5eda4053754b1d0afb65fedd697289c684..c17c4e4afef18a4fc006e7abaf74fd3d87df7526 100644 --- a/src/java.desktop/share/classes/java/awt/im/spi/InputMethodContext.java +++ b/src/java.desktop/share/classes/java/awt/im/spi/InputMethodContext.java @@ -92,7 +92,7 @@ public interface InputMethodContext extends InputMethodRequests { * @param attachToInputContext whether this window should share the input context * that corresponds to this input method context * @return a window with special characteristics for use by input methods - * @exception HeadlessException if {@code GraphicsEnvironment.isHeadless} + * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless} * returns {@code true} */ public Window createInputMethodWindow(String title, boolean attachToInputContext); @@ -124,7 +124,7 @@ public interface InputMethodContext extends InputMethodRequests { * @param attachToInputContext whether this window should share the input context * that corresponds to this input method context * @return a JFrame with special characteristics for use by input methods - * @exception HeadlessException if {@code GraphicsEnvironment.isHeadless} + * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless} * returns {@code true} * * @since 1.4 diff --git a/src/java.desktop/share/classes/java/awt/im/spi/InputMethodDescriptor.java b/src/java.desktop/share/classes/java/awt/im/spi/InputMethodDescriptor.java index 885e7ad4e0981368292785acda66349c8444413a..6e3d8f89706b6007af7d7fd56232eca2087f8ad4 100644 --- a/src/java.desktop/share/classes/java/awt/im/spi/InputMethodDescriptor.java +++ b/src/java.desktop/share/classes/java/awt/im/spi/InputMethodDescriptor.java @@ -63,7 +63,7 @@ public interface InputMethodDescriptor { * unavailable. * * @return the locales supported by the input method - * @exception AWTException if it can be determined that the input method + * @throws AWTException if it can be determined that the input method * is inoperable, for example, because of incomplete installation. */ Locale[] getAvailableLocales() throws AWTException; @@ -122,7 +122,7 @@ public interface InputMethodDescriptor { * Creates a new instance of the corresponding input method. * * @return a new instance of the corresponding input method - * @exception Exception any exception that may occur while creating the + * @throws Exception any exception that may occur while creating the * input method instance */ InputMethod createInputMethod() throws Exception; diff --git a/src/java.desktop/share/classes/java/awt/image/BufferedImage.java b/src/java.desktop/share/classes/java/awt/image/BufferedImage.java index 3c937dd38669bac18051badf4215e31b44813914..770fec6e8ab59c1d5b0d03232d78c54a6643dc3d 100644 --- a/src/java.desktop/share/classes/java/awt/image/BufferedImage.java +++ b/src/java.desktop/share/classes/java/awt/image/BufferedImage.java @@ -594,12 +594,12 @@ public class BufferedImage extends java.awt.Image * the raster has been premultiplied with alpha. * @param properties {@code Hashtable} of * {@code String}/{@code Object} pairs. - * @exception RasterFormatException if the number and + * @throws RasterFormatException if the number and * types of bands in the {@code SampleModel} of the * {@code Raster} do not match the number and types required by * the {@code ColorModel} to represent its color and alpha * components. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code raster} is incompatible with {@code cm} * @see ColorModel * @see Raster @@ -1195,7 +1195,7 @@ public class BufferedImage extends java.awt.Image * @param h the height of the specified rectangular region * @return a {@code BufferedImage} that is the subimage of this * {@code BufferedImage}. - * @exception RasterFormatException if the specified + * @throws RasterFormatException if the specified * area is not contained within this {@code BufferedImage}. */ public BufferedImage getSubimage (int x, int y, int w, int h) { @@ -1391,7 +1391,7 @@ public class BufferedImage extends java.awt.Image * @param tileY the y index of the requested tile in the tile array * @return a {@code Raster} that is the tile defined by the * arguments {@code tileX} and {@code tileY}. - * @exception ArrayIndexOutOfBoundsException if both + * @throws ArrayIndexOutOfBoundsException if both * {@code tileX} and {@code tileY} are not * equal to 0 */ @@ -1561,7 +1561,7 @@ public class BufferedImage extends java.awt.Image * @return {@code true} if the tile specified by the specified * indices is checked out for writing; {@code false} * otherwise. - * @exception ArrayIndexOutOfBoundsException if both + * @throws ArrayIndexOutOfBoundsException if both * {@code tileX} and {@code tileY} are not equal * to 0 */ diff --git a/src/java.desktop/share/classes/java/awt/image/ByteLookupTable.java b/src/java.desktop/share/classes/java/awt/image/ByteLookupTable.java index 01bebc12ee23f66ecd69c699cd9162afef0443d8..2bb5a1219ef3971d3ebf2c481e2c6512fe9e3d74 100644 --- a/src/java.desktop/share/classes/java/awt/image/ByteLookupTable.java +++ b/src/java.desktop/share/classes/java/awt/image/ByteLookupTable.java @@ -117,7 +117,7 @@ public class ByteLookupTable extends LookupTable { * same length as {@code src}. * @return the array {@code dst}, an {@code int} array of * samples. - * @exception ArrayIndexOutOfBoundsException if {@code src} is + * @throws ArrayIndexOutOfBoundsException if {@code src} is * longer than {@code dst} or if for any element * {@code i} of {@code src}, * {@code src[i]-offset} is either less than zero or @@ -168,7 +168,7 @@ public class ByteLookupTable extends LookupTable { * same length as {@code src}. * @return the array {@code dst}, an {@code int} array of * samples. - * @exception ArrayIndexOutOfBoundsException if {@code src} is + * @throws ArrayIndexOutOfBoundsException if {@code src} is * longer than {@code dst} or if for any element * {@code i} of {@code src}, * {@code (src[i]&0xff)-offset} is either less than diff --git a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java index 023b376d73d80e74440a86c7b9767edfb0e9124b..f5ec86a151a018f0ab91c8b675def97a73ee365b 100644 --- a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java +++ b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java @@ -194,9 +194,9 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { * @param profiles the array of {@code ICC_Profile} objects * @param hints the {@code RenderingHints} object used to control * the color conversion, or {@code null} - * @exception IllegalArgumentException when the profile sequence does not + * @throws IllegalArgumentException when the profile sequence does not * specify a well-defined color conversion - * @exception NullPointerException if profiles is null + * @throws NullPointerException if profiles is null */ public ColorConvertOp (ICC_Profile[] profiles, RenderingHints hints) { @@ -242,7 +242,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { * @return {@code dest} color converted from {@code src} * or a new, converted {@code BufferedImage} * if {@code dest} is {@code null} - * @exception IllegalArgumentException if dest is null and this op was + * @throws IllegalArgumentException if dest is null and this op was * constructed using the constructor which takes only a * RenderingHints argument, since the operation is ill defined. */ @@ -456,7 +456,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { * @return {@code dest} color converted from {@code src} * or a new, converted {@code WritableRaster} * if {@code dest} is {@code null} - * @exception IllegalArgumentException if the number of source or + * @throws IllegalArgumentException if the number of source or * destination bands is incorrect, the source or destination * color spaces are undefined, or this op was constructed * with one of the constructors that applies only to diff --git a/src/java.desktop/share/classes/java/awt/image/DirectColorModel.java b/src/java.desktop/share/classes/java/awt/image/DirectColorModel.java index bf7ad07a22e710fd18ddbd4c98b5f86d470ac269..5853f3802a4a07a85f32f637afd2645a3c7f9b50 100644 --- a/src/java.desktop/share/classes/java/awt/image/DirectColorModel.java +++ b/src/java.desktop/share/classes/java/awt/image/DirectColorModel.java @@ -642,12 +642,12 @@ public class DirectColorModel extends PackedColorModel { * @param inData the specified pixel * @return the alpha component of the specified pixel, scaled from * 0 to 255. - * @exception ClassCastException if {@code inData} + * @throws ClassCastException if {@code inData} * is not a primitive array of type {@code transferType} - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * {@code inData} is not large enough to hold a pixel value * for this {@code ColorModel} - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code tranferType} is not supported by this * {@code ColorModel} */ @@ -694,7 +694,7 @@ public class DirectColorModel extends PackedColorModel { * * @param inData the specified pixel * @return the color and alpha components of the specified pixel. - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code transferType} is not supported by this * {@code ColorModel} * @see ColorModel#getRGBdefault @@ -744,12 +744,12 @@ public class DirectColorModel extends PackedColorModel { * @param pixel the specified pixel * @return an array representation of the specified pixel in this * {@code ColorModel} - * @exception ClassCastException if {@code pixel} + * @throws ClassCastException if {@code pixel} * is not a primitive array of type {@code transferType} - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * {@code pixel} is not large enough to hold a pixel value * for this {@code ColorModel} - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code transferType} is not supported by this * {@code ColorModel} * @see WritableRaster#setDataElements @@ -963,14 +963,14 @@ public class DirectColorModel extends PackedColorModel { * which to start storing the color and alpha components * @return an array containing the color and alpha components of the * specified pixel starting at the specified offset. - * @exception ClassCastException if {@code pixel} + * @throws ClassCastException if {@code pixel} * is not a primitive array of type {@code transferType} - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * {@code pixel} is not large enough to hold a pixel value * for this {@code ColorModel}, or if {@code components} * is not {@code null} and is not large enough to hold all the * color and alpha components, starting at {@code offset} - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code transferType} is not supported by this * color model */ @@ -1055,7 +1055,7 @@ public class DirectColorModel extends PackedColorModel { * begin retrieving the color and alpha components * @return an {@code int} pixel value in this * {@code ColorModel} corresponding to the specified components. - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * the {@code components} array is not large enough to * hold all of the color and alpha components starting at * {@code offset} @@ -1097,14 +1097,14 @@ public class DirectColorModel extends PackedColorModel { * and alpha components * @return an {@code Object} representing an array of color and * alpha components. - * @exception ClassCastException if {@code obj} + * @throws ClassCastException if {@code obj} * is not a primitive array of type {@code transferType} - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * {@code obj} is not large enough to hold a pixel value * for this {@code ColorModel} or the {@code components} * array is not large enough to hold all of the color and alpha * components starting at {@code offset} - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code transferType} is not supported by this * color model * @see WritableRaster#setDataElements @@ -1169,7 +1169,7 @@ public class DirectColorModel extends PackedColorModel { * premultiplied; {@code false} otherwise * @return a {@code ColorModel} object that represents the * coerced data. - * @exception UnsupportedOperationException if this + * @throws UnsupportedOperationException if this * {@code transferType} is not supported by this * color model */ diff --git a/src/java.desktop/share/classes/java/awt/image/ImageFilter.java b/src/java.desktop/share/classes/java/awt/image/ImageFilter.java index d136e16fc6b8c3e6fd18f7c101fcf17f24e1df43..94586b851ae71b22e5295dcb70c70be57bd7c7f0 100644 --- a/src/java.desktop/share/classes/java/awt/image/ImageFilter.java +++ b/src/java.desktop/share/classes/java/awt/image/ImageFilter.java @@ -107,7 +107,7 @@ public class ImageFilter implements ImageConsumer, Cloneable { * with the filtering operation. * * @param props the properties from the source object - * @exception NullPointerException if {@code props} is null + * @throws NullPointerException if {@code props} is null */ public void setProperties(Hashtable props) { @SuppressWarnings("unchecked") @@ -245,7 +245,7 @@ public class ImageFilter implements ImageConsumer, Cloneable { * @param ip the ImageProducer that is feeding this instance of * the filter - also the ImageProducer that the request should be * forwarded to if necessary - * @exception NullPointerException if {@code ip} is null + * @throws NullPointerException if {@code ip} is null */ public void resendTopDownLeftRight(ImageProducer ip) { ip.requestTopDownLeftRightResend(this); diff --git a/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java b/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java index dcec78fb34833e0ff4c308c6c1487922ebf58227..9254d9fa71717edfbc055e88f382786d8a3b0830 100644 --- a/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java @@ -130,7 +130,7 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param scanlineStride the line stride of the image data * @param dataBitOffset the data bit offset for the region of image * data described - * @exception RasterFormatException if the number of bits per pixel + * @throws RasterFormatException if the number of bits per pixel * is not a power of 2 or if a power of 2 number of * pixels do not fit in one data element. * @throws IllegalArgumentException if {@code w} or @@ -321,7 +321,7 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param bands the specified bands * @return a new {@code SampleModel} with a subset of bands of * this {@code MultiPixelPackedSampleModel}. - * @exception RasterFormatException if the number of bands requested + * @throws RasterFormatException if the number of bands requested * is not one. * @throws IllegalArgumentException if {@code w} or * {@code h} is not greater than 0 @@ -348,7 +348,7 @@ public class MultiPixelPackedSampleModel extends SampleModel * data * @return the specified band containing the sample of the specified * pixel. - * @exception ArrayIndexOutOfBoundsException if the specified + * @throws ArrayIndexOutOfBoundsException if the specified * coordinates are not in bounds. * @see #setSample(int, int, int, int, DataBuffer) */ @@ -377,7 +377,7 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param b the band to return, which is assumed to be 0 * @param s the input sample as an {@code int} * @param data the {@code DataBuffer} where image data is stored - * @exception ArrayIndexOutOfBoundsException if the coordinates are + * @throws ArrayIndexOutOfBoundsException if the coordinates are * not in bounds. * @see #getSample(int, int, int, DataBuffer) */ @@ -442,9 +442,9 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param data the {@code DataBuffer} containing the image data. * @return an {@code Object} containing data for the specified * pixel. - * @exception ClassCastException if {@code obj} is not a + * @throws ClassCastException if {@code obj} is not a * primitive array of type TransferType or is not {@code null} - * @exception ArrayIndexOutOfBoundsException if the coordinates are + * @throws ArrayIndexOutOfBoundsException if the coordinates are * not in bounds, or if {@code obj} is not {@code null} or * not large enough to hold the pixel data * @see #setDataElements(int, int, Object, DataBuffer) @@ -526,7 +526,7 @@ public class MultiPixelPackedSampleModel extends SampleModel * {@code null} * @param data the {@code DataBuffer} where image data is stored * @return an array containing the specified pixel. - * @exception ArrayIndexOutOfBoundsException if the coordinates + * @throws ArrayIndexOutOfBoundsException if the coordinates * are not in bounds * @see #setPixel(int, int, int[], DataBuffer) */ diff --git a/src/java.desktop/share/classes/java/awt/image/PixelGrabber.java b/src/java.desktop/share/classes/java/awt/image/PixelGrabber.java index 3855316d986d5e7babb8b1eb80160e628cfc9457..fb66a95f5398f9035d0952eca33c094a6b4183f0 100644 --- a/src/java.desktop/share/classes/java/awt/image/PixelGrabber.java +++ b/src/java.desktop/share/classes/java/awt/image/PixelGrabber.java @@ -219,7 +219,7 @@ public class PixelGrabber implements ImageConsumer { * delivered. * @return true if the pixels were successfully grabbed, false on * abort, error or timeout - * @exception InterruptedException + * @throws InterruptedException * Another thread has interrupted this thread. */ public boolean grabPixels() throws InterruptedException { @@ -243,7 +243,7 @@ public class PixelGrabber implements ImageConsumer { * to arrive before timing out * @return true if the pixels were successfully grabbed, false on * abort, error or timeout - * @exception InterruptedException + * @throws InterruptedException * Another thread has interrupted this thread. */ public synchronized boolean grabPixels(long ms) diff --git a/src/java.desktop/share/classes/java/awt/image/RGBImageFilter.java b/src/java.desktop/share/classes/java/awt/image/RGBImageFilter.java index 44302923d1779f0b971918f8f8d36445baa592f0..9838fdfe8b6c3ec60924e62a6ca59e10ab6e7d54 100644 --- a/src/java.desktop/share/classes/java/awt/image/RGBImageFilter.java +++ b/src/java.desktop/share/classes/java/awt/image/RGBImageFilter.java @@ -146,7 +146,7 @@ public abstract class RGBImageFilter extends ImageFilter { * a color table entry is being filtered rather than an actual * pixel value. * @param icm the IndexColorModel object to be filtered - * @exception NullPointerException if {@code icm} is null + * @throws NullPointerException if {@code icm} is null * @return a new IndexColorModel representing the filtered colors */ public IndexColorModel filterIndexColorModel(IndexColorModel icm) { diff --git a/src/java.desktop/share/classes/java/awt/image/Raster.java b/src/java.desktop/share/classes/java/awt/image/Raster.java index 32d45078b3800796f45631cca0c197a5002421a1..d388aa1f79cf4b2d4333a4c605f37686b2f6e262 100644 --- a/src/java.desktop/share/classes/java/awt/image/Raster.java +++ b/src/java.desktop/share/classes/java/awt/image/Raster.java @@ -1375,7 +1375,7 @@ public class Raster { * @param h the specified height of the new {@code WritableRaster} * @return a compatible {@code WritableRaster} with the specified * size and a new sample model and data buffer. - * @exception RasterFormatException if the width or height is less than + * @throws RasterFormatException if the width or height is less than * or equal to zero. */ public WritableRaster createCompatibleWritableRaster(int w, int h) { @@ -1501,7 +1501,7 @@ public class Raster { * of the returned Raster * @param bandList Array of band indices, or null to use all bands * @return a new {@code Raster}. - * @exception RasterFormatException if the specified subregion is outside + * @throws RasterFormatException if the specified subregion is outside * of the raster bounds. * @throws RasterFormatException if {@code width} or * {@code height} diff --git a/src/java.desktop/share/classes/java/awt/image/ShortLookupTable.java b/src/java.desktop/share/classes/java/awt/image/ShortLookupTable.java index 3f4e236b9bc76cd542e5c32f17ca2fdb235950ac..e9c97ad864eb6316c2da9cd2393d5a3d7accfca8 100644 --- a/src/java.desktop/share/classes/java/awt/image/ShortLookupTable.java +++ b/src/java.desktop/share/classes/java/awt/image/ShortLookupTable.java @@ -111,7 +111,7 @@ public class ShortLookupTable extends LookupTable { * same length as {@code src}. * @return the array {@code dst}, an {@code int} array of * samples. - * @exception ArrayIndexOutOfBoundsException if {@code src} is + * @throws ArrayIndexOutOfBoundsException if {@code src} is * longer than {@code dst} or if for any element * {@code i} of {@code src}, * {@code (src[i]&0xffff)-offset} is either less than @@ -162,7 +162,7 @@ public class ShortLookupTable extends LookupTable { * same length as {@code src}. * @return the array {@code dst}, an {@code int} array of * samples. - * @exception ArrayIndexOutOfBoundsException if {@code src} is + * @throws ArrayIndexOutOfBoundsException if {@code src} is * longer than {@code dst} or if for any element * {@code i} of {@code src}, * {@code (src[i]&0xffff)-offset} is either less than diff --git a/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java b/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java index 864ed00cf7617590c71d9de8fc59c50c219d1b1e..abb669e02c6699f2b27c4d17479d3b120d058aa0 100644 --- a/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java @@ -302,7 +302,7 @@ public class SinglePixelPackedSampleModel extends SampleModel * SinglePixelPackedSampleModel/DataBuffer combination will represent * an image with a subset of the bands of the original * SinglePixelPackedSampleModel/DataBuffer combination. - * @exception RasterFormatException if the length of the bands argument is + * @throws RasterFormatException if the length of the bands argument is * greater than the number of bands in * the sample model. */ diff --git a/src/java.desktop/share/classes/java/awt/image/WritableRaster.java b/src/java.desktop/share/classes/java/awt/image/WritableRaster.java index 0e345026c2b526ce5d098221f7e20425c724c687..729317d85a3c9eda95fdb512d8c88322379e37fd 100644 --- a/src/java.desktop/share/classes/java/awt/image/WritableRaster.java +++ b/src/java.desktop/share/classes/java/awt/image/WritableRaster.java @@ -204,7 +204,7 @@ public class WritableRaster extends Raster { * @param bandList Array of band indices, or null to use all bands. * @return a {@code WritableRaster} sharing all or part of the * {@code DataBuffer} of this {@code WritableRaster}. - * @exception RasterFormatException if the subregion is outside of the + * @throws RasterFormatException if the subregion is outside of the * raster bounds. * @throws RasterFormatException if {@code w} or * {@code h} diff --git a/src/java.desktop/share/classes/java/awt/print/PageFormat.java b/src/java.desktop/share/classes/java/awt/print/PageFormat.java index b7709eb581eb36cc1fca8d6c05a83fd4bda06266..019c5d0bdcc1ec533b6bb599ee074f5d4ee0bc22 100644 --- a/src/java.desktop/share/classes/java/awt/print/PageFormat.java +++ b/src/java.desktop/share/classes/java/awt/print/PageFormat.java @@ -286,7 +286,7 @@ public class PageFormat implements Cloneable * {@code PageFormat}. * @param paper the {@code Paper} object to which to set * the {@code Paper} object for this {@code PageFormat}. - * @exception NullPointerException + * @throws NullPointerException * a null paper instance was passed as a parameter. * @see #getPaper */ diff --git a/src/java.desktop/share/classes/java/awt/print/Printable.java b/src/java.desktop/share/classes/java/awt/print/Printable.java index 28a01cc9a16405194be435f64df4d3d476f01eab..1fbf1f7c61620f2a7864f175f7fb868d7d1b3d6e 100644 --- a/src/java.desktop/share/classes/java/awt/print/Printable.java +++ b/src/java.desktop/share/classes/java/awt/print/Printable.java @@ -134,7 +134,7 @@ public interface Printable { * @return PAGE_EXISTS if the page is rendered successfully * or NO_SUCH_PAGE if {@code pageIndex} specifies a * non-existent page. - * @exception java.awt.print.PrinterException + * @throws java.awt.print.PrinterException * thrown when the print job is terminated. */ int print(Graphics graphics, PageFormat pageFormat, int pageIndex) diff --git a/src/java.desktop/share/classes/java/awt/print/PrinterJob.java b/src/java.desktop/share/classes/java/awt/print/PrinterJob.java index 416563671838c5cd2d3aa092e7e962aadf9620b9..ddf565f3ce3b1b0cbe0c6d0c35c143a47d31fe36 100644 --- a/src/java.desktop/share/classes/java/awt/print/PrinterJob.java +++ b/src/java.desktop/share/classes/java/awt/print/PrinterJob.java @@ -168,7 +168,7 @@ public abstract class PrinterJob { * cannot support the {@code Pageable} and * {@code Printable} interfaces necessary to support 2D printing. * @param service a print service that supports 2D printing - * @exception PrinterException if the specified service does not support + * @throws PrinterException if the specified service does not support * 2D printing, or this PrinterJob class does not support * setting a 2D print service, or the specified service is * otherwise not a valid print service. @@ -212,7 +212,7 @@ public abstract class PrinterJob { * {@code document}. * @param document the pages to be printed. It can not be * {@code null}. - * @exception NullPointerException the {@code Pageable} passed in + * @throws NullPointerException the {@code Pageable} passed in * was {@code null}. * @see PageFormat * @see Printable @@ -235,7 +235,7 @@ public abstract class PrinterJob { * selected by the user. * @return {@code true} if the user does not cancel the dialog; * {@code false} otherwise. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -279,9 +279,9 @@ public abstract class PrinterJob { * This parameter may not be null. * @return {@code true} if the user does not cancel the dialog; * {@code false} otherwise. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. - * @exception NullPointerException if {@code attributes} parameter + * @throws NullPointerException if {@code attributes} parameter * is null. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 @@ -313,7 +313,7 @@ public abstract class PrinterJob { * is cancelled; a new {@code PageFormat} object * containing the format indicated by the user if the * dialog is acknowledged. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -342,9 +342,9 @@ public abstract class PrinterJob { * This parameter may not be null. * @return a page format if the user does not cancel the dialog; * {@code null} otherwise. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. - * @exception NullPointerException if {@code attributes} parameter + * @throws NullPointerException if {@code attributes} parameter * is null. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 @@ -495,7 +495,7 @@ public abstract class PrinterJob { /** * Prints a set of pages. - * @exception PrinterException an error in the print system + * @throws PrinterException an error in the print system * caused the job to be aborted. * @see Book * @see Pageable @@ -533,7 +533,7 @@ public abstract class PrinterJob { * this print() method. * * @param attributes a set of attributes for the job - * @exception PrinterException an error in the print system + * @throws PrinterException an error in the print system * caused the job to be aborted. * @see Book * @see Pageable diff --git a/src/java.desktop/share/classes/java/beans/Beans.java b/src/java.desktop/share/classes/java/beans/Beans.java index dbe678b70927e881cc8446bb0e3758bd9f19c8e6..36a424664de35480b36ce4a9d270a1cd02596d5d 100644 --- a/src/java.desktop/share/classes/java/beans/Beans.java +++ b/src/java.desktop/share/classes/java/beans/Beans.java @@ -75,9 +75,9 @@ public class Beans { * @param beanName the name of the bean within the class-loader. * For example "sun.beanbox.foobah" * - * @exception ClassNotFoundException if the class of a serialized + * @throws ClassNotFoundException if the class of a serialized * object could not be found. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException { @@ -97,9 +97,9 @@ public class Beans { * For example "sun.beanbox.foobah" * @param beanContext The BeanContext in which to nest the new bean * - * @exception ClassNotFoundException if the class of a serialized + * @throws ClassNotFoundException if the class of a serialized * object could not be found. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * @since 1.2 */ @SuppressWarnings("deprecation") @@ -156,9 +156,9 @@ public class Beans { * @param beanContext The BeanContext in which to nest the new bean * @param initializer The AppletInitializer for the new bean * - * @exception ClassNotFoundException if the class of a serialized + * @throws ClassNotFoundException if the class of a serialized * object could not be found. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * @since 1.2 * * @deprecated It is recommended to use @@ -432,7 +432,7 @@ public class Beans { * method is called. This could result in a SecurityException. * * @param isDesignTime True if we're in an application builder tool. - * @exception SecurityException if a security manager exists and its + * @throws SecurityException if a security manager exists and its * {@code checkPropertiesAccess} method doesn't allow setting * of system properties. * @see SecurityManager#checkPropertiesAccess @@ -459,7 +459,7 @@ public class Beans { * method is called. This could result in a SecurityException. * * @param isGuiAvailable True if GUI interaction is available. - * @exception SecurityException if a security manager exists and its + * @throws SecurityException if a security manager exists and its * {@code checkPropertiesAccess} method doesn't allow setting * of system properties. * @see SecurityManager#checkPropertiesAccess diff --git a/src/java.desktop/share/classes/java/beans/EventSetDescriptor.java b/src/java.desktop/share/classes/java/beans/EventSetDescriptor.java index 87fa860cf7caf59046832e0bb004ebef150cac29..8826ff27902730b6edc54030f320bd9dae821fef 100644 --- a/src/java.desktop/share/classes/java/beans/EventSetDescriptor.java +++ b/src/java.desktop/share/classes/java/beans/EventSetDescriptor.java @@ -69,7 +69,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * will get delivered to. * @param listenerMethodName The method that will get called when the event gets * delivered to its target listener interface. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public EventSetDescriptor(Class sourceClass, String eventSetName, @@ -114,7 +114,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * that can be used to register an event listener object. * @param removeListenerMethodName The name of the method on the event source * that can be used to de-register an event listener object. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public EventSetDescriptor(Class sourceClass, @@ -146,7 +146,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * that can be used to de-register an event listener object. * @param getListenerMethodName The method on the event source that * can be used to access the array of event listener objects. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. * @since 1.4 */ @@ -210,7 +210,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * that can be used to register an event listener object. * @param removeListenerMethod The method on the event source * that can be used to de-register an event listener object. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public EventSetDescriptor(String eventSetName, @@ -237,7 +237,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * that can be used to de-register an event listener object. * @param getListenerMethod The method on the event source * that can be used to access the array of event listener objects. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. * @since 1.4 */ @@ -280,7 +280,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * that can be used to register an event listener object. * @param removeListenerMethod The method on the event source * that can be used to de-register an event listener object. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public EventSetDescriptor(String eventSetName, diff --git a/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java b/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java index b49b1cb07a950673185fe6fcfca011f347fa5a16..a46c8ec9d6e7b64ecdaf3d7715d0c7abaf98a8f7 100644 --- a/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -63,7 +63,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * * @param propertyName The programmatic name of the property. * @param beanClass The Class object for the target bean. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public IndexedPropertyDescriptor(String propertyName, Class beanClass) @@ -94,7 +94,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * @param indexedWriteMethodName The name of the method used for writing * an indexed property value. * May be null if the property is read-only. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public IndexedPropertyDescriptor(String propertyName, Class beanClass, @@ -129,7 +129,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * May be null if the property is write-only. * @param indexedWriteMethod The method used for writing an indexed property value. * May be null if the property is read-only. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod, diff --git a/src/java.desktop/share/classes/java/beans/Introspector.java b/src/java.desktop/share/classes/java/beans/Introspector.java index f73444a54ef9d4b0e05fb1b9cf3255b274df093c..88225ab01d4e703f4b0b401bd299a4de5f83f086 100644 --- a/src/java.desktop/share/classes/java/beans/Introspector.java +++ b/src/java.desktop/share/classes/java/beans/Introspector.java @@ -178,7 +178,7 @@ public class Introspector { * * @param beanClass The bean class to be analyzed. * @return A BeanInfo object describing the target bean. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. * @see #flushCaches * @see #flushFromCaches @@ -216,7 +216,7 @@ public class Introspector { * associated with the specified beanClass or any of its * parent classes. * @return A BeanInfo object describing the target bean. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. * @since 1.2 */ @@ -237,7 +237,7 @@ public class Introspector { * @param stopClass The baseclass at which to stop the analysis. Any * methods/properties/events in the stopClass or in its baseclasses * will be ignored in the analysis. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) @@ -269,7 +269,7 @@ public class Introspector { * @param stopClass the parent class at which to stop the analysis * @param flags flags to control the introspection * @return a BeanInfo object describing the target bean - * @exception IntrospectionException if an exception occurs during introspection + * @throws IntrospectionException if an exception occurs during introspection * * @since 1.7 */ @@ -339,7 +339,7 @@ public class Introspector { * method is called. This could result in a SecurityException. * * @param path Array of package names. - * @exception SecurityException if a security manager exists and its + * @throws SecurityException if a security manager exists and its * {@code checkPropertiesAccess} method doesn't allow setting * of system properties. * @see SecurityManager#checkPropertiesAccess diff --git a/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java b/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java index d63c446f37375e8b9af3f28fc9167998cdc99290..ae4bb69c18cf43ca26b3de96677e982fbcd4e6f5 100644 --- a/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java +++ b/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java @@ -66,7 +66,7 @@ public class PropertyDescriptor extends FeatureDescriptor { * @param propertyName The programmatic name of the property. * @param beanClass The Class object for the target bean. For * example sun.beans.OurButton.class. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public PropertyDescriptor(String propertyName, Class beanClass) @@ -87,7 +87,7 @@ public class PropertyDescriptor extends FeatureDescriptor { * value. May be null if the property is write-only. * @param writeMethodName The name of the method used for writing the property * value. May be null if the property is read-only. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public PropertyDescriptor(String propertyName, Class beanClass, @@ -129,7 +129,7 @@ public class PropertyDescriptor extends FeatureDescriptor { * May be null if the property is write-only. * @param writeMethod The method used for writing the property value. * May be null if the property is read-only. - * @exception IntrospectionException if an exception occurs during + * @throws IntrospectionException if an exception occurs during * introspection. */ public PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod) diff --git a/src/java.desktop/share/classes/java/beans/PropertyEditorManager.java b/src/java.desktop/share/classes/java/beans/PropertyEditorManager.java index 3642c0c58be518d6fe9988b2cb3d3708474d942f..a692c9214212207ea0bfa232960f8dd323403443 100644 --- a/src/java.desktop/share/classes/java/beans/PropertyEditorManager.java +++ b/src/java.desktop/share/classes/java/beans/PropertyEditorManager.java @@ -118,7 +118,7 @@ public class PropertyEditorManager { * method is called. This could result in a SecurityException. * * @param path Array of package names. - * @exception SecurityException if a security manager exists and its + * @throws SecurityException if a security manager exists and its * {@code checkPropertiesAccess} method doesn't allow setting * of system properties. * @see SecurityManager#checkPropertiesAccess diff --git a/src/java.desktop/share/classes/java/beans/VetoableChangeListener.java b/src/java.desktop/share/classes/java/beans/VetoableChangeListener.java index ae473becad91423a7a4b0c9700a61a96d5e7152a..1c20a9926e55341102a76c8930da98383eedb142 100644 --- a/src/java.desktop/share/classes/java/beans/VetoableChangeListener.java +++ b/src/java.desktop/share/classes/java/beans/VetoableChangeListener.java @@ -37,7 +37,7 @@ public interface VetoableChangeListener extends java.util.EventListener { * * @param evt a {@code PropertyChangeEvent} object describing the * event source and the property that has changed. - * @exception PropertyVetoException if the recipient wishes the property + * @throws PropertyVetoException if the recipient wishes the property * change to be rolled back. */ void vetoableChange(PropertyChangeEvent evt) diff --git a/src/java.desktop/share/classes/java/beans/VetoableChangeListenerProxy.java b/src/java.desktop/share/classes/java/beans/VetoableChangeListenerProxy.java index 9a0438790c12f01288851bdb3ca14f48a40aa0ac..4e4ad96ebd8dc7bd8f792bc1a2611ba40bea7949 100644 --- a/src/java.desktop/share/classes/java/beans/VetoableChangeListenerProxy.java +++ b/src/java.desktop/share/classes/java/beans/VetoableChangeListenerProxy.java @@ -66,7 +66,7 @@ public class VetoableChangeListenerProxy * * @param event the property change event * - * @exception PropertyVetoException if the recipient wishes the property + * @throws PropertyVetoException if the recipient wishes the property * change to be rolled back */ public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{ diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java index 13279894ce6ef7772be0e04ab91a5f434a2fdfdb..ecdd4794d38b560b31c868fb7c6ba099533d8d4b 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java @@ -81,7 +81,7 @@ public class BeanContextMembershipEvent extends BeanContextEvent { * * @param bc The BeanContext source * @param changes The Children effected - * @exception NullPointerException if changes associated with this + * @throws NullPointerException if changes associated with this * event are null. */ diff --git a/src/java.desktop/share/classes/javax/imageio/IIOImage.java b/src/java.desktop/share/classes/javax/imageio/IIOImage.java index ad1c18444ef7527ffc6f4f7722a79a106c5765ec..c830189d0ba5aed6114e484279730692652ef907 100644 --- a/src/java.desktop/share/classes/javax/imageio/IIOImage.java +++ b/src/java.desktop/share/classes/javax/imageio/IIOImage.java @@ -99,7 +99,7 @@ public class IIOImage { * @param metadata an {@code IIOMetadata} object, or * {@code null}. * - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. */ public IIOImage(RenderedImage image, @@ -127,7 +127,7 @@ public class IIOImage { * @param metadata an {@code IIOMetadata} object, or * {@code null}. * - * @exception IllegalArgumentException if {@code raster} is + * @throws IllegalArgumentException if {@code raster} is * {@code null}. */ public IIOImage(Raster raster, @@ -163,7 +163,7 @@ public class IIOImage { * * @param image a {@code RenderedImage}. * - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. * * @see #getRenderedImage @@ -213,7 +213,7 @@ public class IIOImage { * * @param raster a {@code Raster}. * - * @exception IllegalArgumentException if {@code raster} is + * @throws IllegalArgumentException if {@code raster} is * {@code null}. * * @see #getRaster @@ -245,9 +245,9 @@ public class IIOImage { * * @return a thumbnail image, as a {@code BufferedImage}. * - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * negative or larger than the largest valid index. - * @exception ClassCastException if a + * @throws ClassCastException if a * non-{@code BufferedImage} object is encountered in the * list of thumbnails at the given index. * diff --git a/src/java.desktop/share/classes/javax/imageio/IIOParam.java b/src/java.desktop/share/classes/javax/imageio/IIOParam.java index 360ec5328955a4066b0d0e02e762efe0f4b001bb..36b10f1eacc3aff08090a260e3212e84cc059f4b 100644 --- a/src/java.desktop/share/classes/javax/imageio/IIOParam.java +++ b/src/java.desktop/share/classes/javax/imageio/IIOParam.java @@ -162,15 +162,15 @@ public abstract class IIOParam { * @param sourceRegion a {@code Rectangle} specifying the * source region of interest, or {@code null}. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code sourceRegion} is non-{@code null} and either * {@code sourceRegion.x} or {@code sourceRegion.y} is * negative. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code sourceRegion} is non-{@code null} and either * {@code sourceRegion.width} or * {@code sourceRegion.height} is negative or 0. - * @exception IllegalStateException if subsampling is such that + * @throws IllegalStateException if subsampling is such that * this region will have a subsampled width or height of zero. * * @see #getSourceRegion @@ -290,10 +290,10 @@ public abstract class IIOParam { * within the region, or within the image if no region is set. * @param subsamplingYOffset the horizontal offset of the first subsample * within the region, or within the image if no region is set. - * @exception IllegalArgumentException if either period is + * @throws IllegalArgumentException if either period is * negative or 0, or if either grid offset is negative or greater than * the corresponding period. - * @exception IllegalStateException if the source region is such that + * @throws IllegalStateException if the source region is such that * the subsampled output would contain no pixels. */ public void setSourceSubsampling(int sourceXSubsampling, @@ -413,7 +413,7 @@ public abstract class IIOParam { * @param sourceBands an array of integer band indices to be * used. * - * @exception IllegalArgumentException if {@code sourceBands} + * @throws IllegalArgumentException if {@code sourceBands} * contains a negative or duplicate value. * * @see #getSourceBands @@ -537,7 +537,7 @@ public abstract class IIOParam { * @param destinationOffset the offset in the destination, as a * {@code Point}. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code destinationOffset} is {@code null}. * * @see #getDestinationOffset @@ -658,7 +658,7 @@ public abstract class IIOParam { * * @return {@code true} if the controller completed normally. * - * @exception IllegalStateException if there is no controller + * @throws IllegalStateException if there is no controller * currently installed. * * @see IIOParamController diff --git a/src/java.desktop/share/classes/javax/imageio/IIOParamController.java b/src/java.desktop/share/classes/javax/imageio/IIOParamController.java index 5d8a7017ccd12dd0fd547682702696a3930e0f57..9389a0093cd3a8fb3a08cd66909a6edbbb91850d 100644 --- a/src/java.desktop/share/classes/javax/imageio/IIOParamController.java +++ b/src/java.desktop/share/classes/javax/imageio/IIOParamController.java @@ -111,7 +111,7 @@ public interface IIOParamController { * @return {@code true} if the {@code IIOParam} has been * modified, {@code false} otherwise. * - * @exception IllegalArgumentException if {@code param} is + * @throws IllegalArgumentException if {@code param} is * {@code null} or is not an instance of the correct class. */ boolean activate(IIOParam param); diff --git a/src/java.desktop/share/classes/javax/imageio/ImageIO.java b/src/java.desktop/share/classes/javax/imageio/ImageIO.java index 8c62ef92b116bd11546fe61dc90740bf909170e9..9e87640967bd30d54bbbdf521bf72326f7fb99bc 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageIO.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageIO.java @@ -277,9 +277,9 @@ public final class ImageIO { * * @see File#createTempFile(String, String, File) * - * @exception SecurityException if the security manager denies + * @throws SecurityException if the security manager denies * access to the directory. - * @exception IllegalArgumentException if {@code cacheDir} is + * @throws IllegalArgumentException if {@code cacheDir} is * non-{@code null} but is not a directory. * * @see #getCacheDirectory @@ -326,9 +326,9 @@ public final class ImageIO { * * @return an {@code ImageInputStream}, or {@code null}. * - * @exception IllegalArgumentException if {@code input} + * @throws IllegalArgumentException if {@code input} * is {@code null}. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see javax.imageio.spi.ImageInputStreamSpi @@ -388,9 +388,9 @@ public final class ImageIO { * @return an {@code ImageOutputStream}, or * {@code null}. * - * @exception IllegalArgumentException if {@code output} is + * @throws IllegalArgumentException if {@code output} is * {@code null}. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see javax.imageio.spi.ImageOutputStreamSpi @@ -637,7 +637,7 @@ public final class ImageIO { * * @return an {@code Iterator} containing {@code ImageReader}s. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * {@code null}. * * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput @@ -697,7 +697,7 @@ public final class ImageIO { * @return an {@code Iterator} containing * {@code ImageReader}s. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null}. * * @see javax.imageio.spi.ImageReaderSpi#getFormatNames @@ -732,7 +732,7 @@ public final class ImageIO { * @return an {@code Iterator} containing * {@code ImageReader}s. * - * @exception IllegalArgumentException if {@code fileSuffix} + * @throws IllegalArgumentException if {@code fileSuffix} * is {@code null}. * * @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes @@ -767,7 +767,7 @@ public final class ImageIO { * @return an {@code Iterator} containing * {@code ImageReader}s. * - * @exception IllegalArgumentException if {@code MIMEType} is + * @throws IllegalArgumentException if {@code MIMEType} is * {@code null}. * * @see javax.imageio.spi.ImageReaderSpi#getMIMETypes @@ -880,7 +880,7 @@ public final class ImageIO { * @return an {@code Iterator} containing * {@code ImageWriter}s. * - * @exception IllegalArgumentException if {@code formatName} is + * @throws IllegalArgumentException if {@code formatName} is * {@code null}. * * @see javax.imageio.spi.ImageWriterSpi#getFormatNames @@ -914,7 +914,7 @@ public final class ImageIO { * * @return an {@code Iterator} containing {@code ImageWriter}s. * - * @exception IllegalArgumentException if {@code fileSuffix} is + * @throws IllegalArgumentException if {@code fileSuffix} is * {@code null}. * * @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes @@ -948,7 +948,7 @@ public final class ImageIO { * * @return an {@code Iterator} containing {@code ImageWriter}s. * - * @exception IllegalArgumentException if {@code MIMEType} is + * @throws IllegalArgumentException if {@code MIMEType} is * {@code null}. * * @see javax.imageio.spi.ImageWriterSpi#getMIMETypes @@ -995,7 +995,7 @@ public final class ImageIO { * * @return an {@code ImageWriter}, or null. * - * @exception IllegalArgumentException if {@code reader} is + * @throws IllegalArgumentException if {@code reader} is * {@code null}. * * @see #getImageReader(ImageWriter) @@ -1075,7 +1075,7 @@ public final class ImageIO { * * @return an {@code ImageReader}, or null. * - * @exception IllegalArgumentException if {@code writer} is + * @throws IllegalArgumentException if {@code writer} is * {@code null}. * * @see #getImageWriter(ImageReader) @@ -1151,7 +1151,7 @@ public final class ImageIO { * * @return an {@code Iterator} containing {@code ImageWriter}s. * - * @exception IllegalArgumentException if any parameter is + * @throws IllegalArgumentException if any parameter is * {@code null}. * * @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier) @@ -1238,7 +1238,7 @@ public final class ImageIO { * @return an {@code Iterator} containing * {@code ImageTranscoder}s. * - * @exception IllegalArgumentException if {@code reader} or + * @throws IllegalArgumentException if {@code reader} or * {@code writer} is {@code null}. */ public static Iterator @@ -1295,9 +1295,9 @@ public final class ImageIO { * @return a {@code BufferedImage} containing the decoded * contents of the input, or {@code null}. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading or when not + * @throws IOException if an error occurs during reading or when not * able to create required ImageInputStream. */ public static BufferedImage read(File input) throws IOException { @@ -1346,9 +1346,9 @@ public final class ImageIO { * @return a {@code BufferedImage} containing the decoded * contents of the input, or {@code null}. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading or when not + * @throws IOException if an error occurs during reading or when not * able to create required ImageInputStream. */ public static BufferedImage read(InputStream input) throws IOException { @@ -1390,9 +1390,9 @@ public final class ImageIO { * @return a {@code BufferedImage} containing the decoded * contents of the input, or {@code null}. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading or when not + * @throws IOException if an error occurs during reading or when not * able to create required ImageInputStream. */ public static BufferedImage read(URL input) throws IOException { @@ -1443,9 +1443,9 @@ public final class ImageIO { * @return a {@code BufferedImage} containing the decoded * contents of the input, or {@code null}. * - * @exception IllegalArgumentException if {@code stream} is + * @throws IllegalArgumentException if {@code stream} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public static BufferedImage read(ImageInputStream stream) throws IOException { @@ -1489,9 +1489,9 @@ public final class ImageIO { * * @return {@code false} if no appropriate writer is found. * - * @exception IllegalArgumentException if any parameter is + * @throws IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public static boolean write(RenderedImage im, String formatName, @@ -1522,9 +1522,9 @@ public final class ImageIO { * * @return {@code false} if no appropriate writer is found. * - * @exception IllegalArgumentException if any parameter is + * @throws IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing or when not + * @throws IOException if an error occurs during writing or when not * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, @@ -1570,9 +1570,9 @@ public final class ImageIO { * * @return {@code false} if no appropriate writer is found. * - * @exception IllegalArgumentException if any parameter is + * @throws IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing or when not + * @throws IOException if an error occurs during writing or when not * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, diff --git a/src/java.desktop/share/classes/javax/imageio/ImageReadParam.java b/src/java.desktop/share/classes/javax/imageio/ImageReadParam.java index d2181a18115cd6d5d465f3a14185371d3fdcab79..00866f60e7b135d85322a735861b16fc23883fd7 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageReadParam.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageReadParam.java @@ -272,7 +272,7 @@ public class ImageReadParam extends IIOParam { * @param destinationBands an array of integer band indices to be * used. * - * @exception IllegalArgumentException if {@code destinationBands} + * @throws IllegalArgumentException if {@code destinationBands} * contains a negative or duplicate value. * * @see #getDestinationBands @@ -360,9 +360,9 @@ public class ImageReadParam extends IIOParam { * @param size a {@code Dimension} indicating the desired * width and height. * - * @exception IllegalArgumentException if either the width or the + * @throws IllegalArgumentException if either the width or the * height is negative or 0. - * @exception UnsupportedOperationException if image resizing + * @throws UnsupportedOperationException if image resizing * is not supported by this plug-in. * * @see #getSourceRenderSize @@ -433,7 +433,7 @@ public class ImageReadParam extends IIOParam { * @param minPass the index of the first pass to be decoded. * @param numPasses the maximum number of passes to be decoded. * - * @exception IllegalArgumentException if {@code minPass} is + * @throws IllegalArgumentException if {@code minPass} is * negative, {@code numPasses} is negative or 0, or * {@code numPasses} is smaller than * {@code Integer.MAX_VALUE} but diff --git a/src/java.desktop/share/classes/javax/imageio/ImageReader.java b/src/java.desktop/share/classes/javax/imageio/ImageReader.java index e17a5f2e7962598696a6318613a9547ff3e59708..97092ec7de9c6cca08155c1a3b0bcef78a71ac26 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageReader.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageReader.java @@ -196,7 +196,7 @@ public abstract class ImageReader { * provider, or which desire a different naming policy should * override this method. * - * @exception IOException if an error occurs reading the + * @throws IOException if an error occurs reading the * information from the input source. * * @return the format name, as a {@code String}. @@ -276,7 +276,7 @@ public abstract class ImageReader { * @param ignoreMetadata if {@code true}, metadata * may be ignored during reads. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * not an instance of one of the classes returned by the * originating service provider's {@code getInputTypes} * method, or is not an {@code ImageInputStream}. @@ -343,7 +343,7 @@ public abstract class ImageReader { * @param seekForwardOnly if {@code true}, images and metadata * may only be read in ascending order from this input source. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * not an instance of one of the classes returned by the * originating service provider's {@code getInputTypes} * method, or is not an {@code ImageInputStream}. @@ -369,7 +369,7 @@ public abstract class ImageReader { * @param input the {@code ImageInputStream} or other * {@code Object} to use for future decoding. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * not an instance of one of the classes returned by the * originating service provider's {@code getInputTypes} * method, or is not an {@code ImageInputStream}. @@ -470,7 +470,7 @@ public abstract class ImageReader { * @param locale the desired {@code Locale}, or * {@code null}. * - * @exception IllegalArgumentException if {@code locale} is + * @throws IllegalArgumentException if {@code locale} is * non-{@code null} but is not one of the values returned by * {@code getAvailableLocales}. * @@ -538,10 +538,10 @@ public abstract class ImageReader { * {@code -1} if {@code allowSearch} is * {@code false} and a search would be required. * - * @exception IllegalStateException if the input source has not been set, + * @throws IllegalStateException if the input source has not been set, * or if the input has been specified with {@code seekForwardOnly} * set to {@code true}. - * @exception IOException if an error occurs reading the + * @throws IOException if an error occurs reading the * information from the input source. * * @see #setInput @@ -559,10 +559,10 @@ public abstract class ImageReader { * * @return the width of the image, as an {@code int}. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs reading the width + * @throws IOException if an error occurs reading the width * information from the input source. */ public abstract int getWidth(int imageIndex) throws IOException; @@ -578,10 +578,10 @@ public abstract class ImageReader { * * @return the height of the image, as an {@code int}. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs reading the height + * @throws IOException if an error occurs reading the height * information from the input source. */ public abstract int getHeight(int imageIndex) throws IOException; @@ -617,12 +617,12 @@ public abstract class ImageReader { * @return {@code true} if reading a region of interest of * the given image is likely to be efficient. * - * @exception IllegalStateException if an input source is required + * @throws IllegalStateException if an input source is required * to determine the return value, but none has been set. - * @exception IndexOutOfBoundsException if an image must be + * @throws IndexOutOfBoundsException if an image must be * accessed to determine the return value, but the supplied index * is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public boolean isRandomAccessEasy(int imageIndex) throws IOException { return false; @@ -644,10 +644,10 @@ public abstract class ImageReader { * @return a {@code float} indicating the aspect ratio of the * given image. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public float getAspectRatio(int imageIndex) throws IOException { return (float)getWidth(imageIndex)/getHeight(imageIndex); @@ -669,10 +669,10 @@ public abstract class ImageReader { * * @return an {@code ImageTypeSpecifier}. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs reading the format + * @throws IOException if an error occurs reading the format * information from the input source. */ public ImageTypeSpecifier getRawImageType(int imageIndex) @@ -699,10 +699,10 @@ public abstract class ImageReader { * {@code ImageTypeSpecifier} representing suggested image * types for decoding the current given image. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs reading the format + * @throws IOException if an error occurs reading the format * information from the input source. * * @see ImageReadParam#setDestination(BufferedImage) @@ -739,7 +739,7 @@ public abstract class ImageReader { * * @return an {@code IIOMetadata} object, or {@code null}. * - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public abstract IIOMetadata getStreamMetadata() throws IOException; @@ -778,11 +778,11 @@ public abstract class ImageReader { * * @return an {@code IIOMetadata} object, or {@code null}. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null}. - * @exception IllegalArgumentException if {@code nodeNames} + * @throws IllegalArgumentException if {@code nodeNames} * is {@code null}. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public IIOMetadata getStreamMetadata(String formatName, Set nodeNames) @@ -839,11 +839,11 @@ public abstract class ImageReader { * @return an {@code IIOMetadata} object, or * {@code null}. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public abstract IIOMetadata getImageMetadata(int imageIndex) throws IOException; @@ -885,15 +885,15 @@ public abstract class ImageReader { * * @return an {@code IIOMetadata} object, or {@code null}. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null}. - * @exception IllegalArgumentException if {@code nodeNames} + * @throws IllegalArgumentException if {@code nodeNames} * is {@code null}. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public IIOMetadata getImageMetadata(int imageIndex, String formatName, @@ -928,11 +928,11 @@ public abstract class ImageReader { * @return the desired portion of the image as a * {@code BufferedImage}. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public BufferedImage read(int imageIndex) throws IOException { return read(imageIndex, null); @@ -980,18 +980,18 @@ public abstract class ImageReader { * @return the desired portion of the image as a * {@code BufferedImage}. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IllegalArgumentException if the set of source and + * @throws IllegalArgumentException if the set of source and * destination bands specified by * {@code param.getSourceBands} and * {@code param.getDestinationBands} differ in length or * include indices that are out of bounds. - * @exception IllegalArgumentException if the resulting image would + * @throws IllegalArgumentException if the resulting image would * have a width or height less than 1. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public abstract BufferedImage read(int imageIndex, ImageReadParam param) throws IOException; @@ -1043,18 +1043,18 @@ public abstract class ImageReader { * of the image, a set of thumbnails, and associated image * metadata. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IllegalArgumentException if the set of source and + * @throws IllegalArgumentException if the set of source and * destination bands specified by * {@code param.getSourceBands} and * {@code param.getDestinationBands} differ in length or * include indices that are out of bounds. - * @exception IllegalArgumentException if the resulting image + * @throws IllegalArgumentException if the resulting image * would have a width or height less than 1. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public IIOImage readAll(int imageIndex, ImageReadParam param) throws IOException { @@ -1134,19 +1134,19 @@ public abstract class ImageReader { * @return an {@code Iterator} representing the * contents of the input source as {@code IIOImage}s. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IllegalArgumentException if any + * @throws IllegalArgumentException if any * non-{@code null} element of {@code params} is not an * {@code ImageReadParam}. - * @exception IllegalArgumentException if the set of source and + * @throws IllegalArgumentException if the set of source and * destination bands specified by * {@code param.getSourceBands} and * {@code param.getDestinationBands} differ in length or * include indices that are out of bounds. - * @exception IllegalArgumentException if a resulting image would + * @throws IllegalArgumentException if a resulting image would * have a width or height less than 1. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. * * @see ImageReadParam * @see IIOImage @@ -1267,13 +1267,13 @@ public abstract class ImageReader { * @return the desired portion of the image as a * {@code Raster}. * - * @exception UnsupportedOperationException if this plug-in does not + * @throws UnsupportedOperationException if this plug-in does not * support reading raw {@code Raster}s. - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. * * @see #canReadRaster * @see #read @@ -1310,12 +1310,12 @@ public abstract class ImageReader { * * @return {@code true} if the image is tiled. * - * @exception IllegalStateException if an input source is required + * @throws IllegalStateException if an input source is required * to determine the return value, but none has been set. - * @exception IndexOutOfBoundsException if an image must be + * @throws IndexOutOfBoundsException if an image must be * accessed to determine the return value, but the supplied index * is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public boolean isImageTiled(int imageIndex) throws IOException { return false; @@ -1333,10 +1333,10 @@ public abstract class ImageReader { * * @param imageIndex the index of the image to be queried. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getTileWidth(int imageIndex) throws IOException { return getWidth(imageIndex); @@ -1354,10 +1354,10 @@ public abstract class ImageReader { * * @param imageIndex the index of the image to be queried. * - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getTileHeight(int imageIndex) throws IOException { return getHeight(imageIndex); @@ -1382,12 +1382,12 @@ public abstract class ImageReader { * * @param imageIndex the index of the image to be queried. * - * @exception IllegalStateException if an input source is required + * @throws IllegalStateException if an input source is required * to determine the return value, but none has been set. - * @exception IndexOutOfBoundsException if an image must be + * @throws IndexOutOfBoundsException if an image must be * accessed to determine the return value, but the supplied index * is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getTileGridXOffset(int imageIndex) throws IOException { return 0; @@ -1412,12 +1412,12 @@ public abstract class ImageReader { * * @param imageIndex the index of the image to be queried. * - * @exception IllegalStateException if an input source is required + * @throws IllegalStateException if an input source is required * to determine the return value, but none has been set. - * @exception IndexOutOfBoundsException if an image must be + * @throws IndexOutOfBoundsException if an image must be * accessed to determine the return value, but the supplied index * is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getTileGridYOffset(int imageIndex) throws IOException { return 0; @@ -1455,13 +1455,13 @@ public abstract class ImageReader { * * @return the tile as a {@code BufferedImage}. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is out of bounds. - * @exception IllegalArgumentException if the tile indices are + * @throws IllegalArgumentException if the tile indices are * out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public BufferedImage readTile(int imageIndex, int tileX, int tileY) throws IOException { @@ -1495,15 +1495,15 @@ public abstract class ImageReader { * * @return the tile as a {@code Raster}. * - * @exception UnsupportedOperationException if this plug-in does not + * @throws UnsupportedOperationException if this plug-in does not * support reading raw {@code Raster}s. - * @exception IllegalArgumentException if the tile indices are + * @throws IllegalArgumentException if the tile indices are * out of bounds. - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. * * @see #readTile * @see #readRaster @@ -1554,18 +1554,18 @@ public abstract class ImageReader { * @return a {@code RenderedImage} object providing a view of * the image. * - * @exception IllegalStateException if the input source has not been + * @throws IllegalStateException if the input source has not been * set. - * @exception IndexOutOfBoundsException if the supplied index is + * @throws IndexOutOfBoundsException if the supplied index is * out of bounds. - * @exception IllegalArgumentException if the set of source and + * @throws IllegalArgumentException if the set of source and * destination bands specified by * {@code param.getSourceBands} and * {@code param.getDestinationBands} differ in length or * include indices that are out of bounds. - * @exception IllegalArgumentException if the resulting image + * @throws IllegalArgumentException if the resulting image * would have a width or height less than 1. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param) @@ -1611,11 +1611,11 @@ public abstract class ImageReader { * * @return {@code true} if the given image has thumbnails. * - * @exception IllegalStateException if the reader supports + * @throws IllegalStateException if the reader supports * thumbnails but the input source has not been set. - * @exception IndexOutOfBoundsException if the reader supports + * @throws IndexOutOfBoundsException if the reader supports * thumbnails but {@code imageIndex} is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public boolean hasThumbnails(int imageIndex) throws IOException { return getNumThumbnails(imageIndex) > 0; @@ -1637,11 +1637,11 @@ public abstract class ImageReader { * @return the number of thumbnails associated with the given * image. * - * @exception IllegalStateException if the reader supports + * @throws IllegalStateException if the reader supports * thumbnails but the input source has not been set. - * @exception IndexOutOfBoundsException if the reader supports + * @throws IndexOutOfBoundsException if the reader supports * thumbnails but {@code imageIndex} is out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getNumThumbnails(int imageIndex) throws IOException { @@ -1669,12 +1669,12 @@ public abstract class ImageReader { * * @return the width of the desired thumbnail as an {@code int}. * - * @exception UnsupportedOperationException if thumbnails are not + * @throws UnsupportedOperationException if thumbnails are not * supported. - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if either of the supplied + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if either of the supplied * indices are out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getThumbnailWidth(int imageIndex, int thumbnailIndex) throws IOException { @@ -1702,12 +1702,12 @@ public abstract class ImageReader { * * @return the height of the desired thumbnail as an {@code int}. * - * @exception UnsupportedOperationException if thumbnails are not + * @throws UnsupportedOperationException if thumbnails are not * supported. - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if either of the supplied + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if either of the supplied * indices are out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public int getThumbnailHeight(int imageIndex, int thumbnailIndex) throws IOException { @@ -1738,12 +1738,12 @@ public abstract class ImageReader { * * @return the desired thumbnail as a {@code BufferedImage}. * - * @exception UnsupportedOperationException if thumbnails are not + * @throws UnsupportedOperationException if thumbnails are not * supported. - * @exception IllegalStateException if the input source has not been set. - * @exception IndexOutOfBoundsException if either of the supplied + * @throws IllegalStateException if the input source has not been set. + * @throws IndexOutOfBoundsException if either of the supplied * indices are out of bounds. - * @exception IOException if an error occurs during reading. + * @throws IOException if an error occurs during reading. */ public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) @@ -2388,7 +2388,7 @@ public abstract class ImageReader { * * @param warning the warning message to send. * - * @exception IllegalArgumentException if {@code warning} + * @throws IllegalArgumentException if {@code warning} * is {@code null}. */ protected void processWarningOccurred(String warning) { @@ -2420,15 +2420,15 @@ public abstract class ImageReader { * @param keyword the keyword used to index the warning message * within the set of {@code ResourceBundle}s. * - * @exception IllegalArgumentException if {@code baseName} + * @throws IllegalArgumentException if {@code baseName} * is {@code null}. - * @exception IllegalArgumentException if {@code keyword} + * @throws IllegalArgumentException if {@code keyword} * is {@code null}. - * @exception IllegalArgumentException if no appropriate + * @throws IllegalArgumentException if no appropriate * {@code ResourceBundle} may be located. - * @exception IllegalArgumentException if the named resource is + * @throws IllegalArgumentException if the named resource is * not found in the located {@code ResourceBundle}. - * @exception IllegalArgumentException if the object retrieved + * @throws IllegalArgumentException if the object retrieved * from the {@code ResourceBundle} is not a * {@code String}. */ @@ -2594,11 +2594,11 @@ public abstract class ImageReader { * the source region of interest. * @param destRegion a {@code Rectangle} that will be filled with * the destination region of interest. - * @exception IllegalArgumentException if {@code srcRegion} + * @throws IllegalArgumentException if {@code srcRegion} * is {@code null}. - * @exception IllegalArgumentException if {@code dstRegion} + * @throws IllegalArgumentException if {@code dstRegion} * is {@code null}. - * @exception IllegalArgumentException if the resulting source or + * @throws IllegalArgumentException if the resulting source or * destination region is empty. */ protected static void computeRegions(ImageReadParam param, @@ -2720,7 +2720,7 @@ public abstract class ImageReader { * @param numDstBands the number of bands in the destination image * being written. * - * @exception IllegalArgumentException if {@code param} + * @throws IllegalArgumentException if {@code param} * contains an invalid specification of a source and/or * destination band subset. */ @@ -2797,15 +2797,15 @@ public abstract class ImageReader { * @return the {@code BufferedImage} to which decoded pixel * data should be written. * - * @exception IIOException if the {@code ImageTypeSpecifier} + * @throws IIOException if the {@code ImageTypeSpecifier} * specified by {@code param} does not match any of the legal * ones from {@code imageTypes}. - * @exception IllegalArgumentException if {@code imageTypes} + * @throws IllegalArgumentException if {@code imageTypes} * is {@code null} or empty, or if an object not of type * {@code ImageTypeSpecifier} is retrieved from it. - * @exception IllegalArgumentException if the resulting image would + * @throws IllegalArgumentException if the resulting image would * have a width or height less than 1. - * @exception IllegalArgumentException if the product of + * @throws IllegalArgumentException if the product of * {@code width} and {@code height} is greater than * {@code Integer.MAX_VALUE}. */ diff --git a/src/java.desktop/share/classes/javax/imageio/ImageTranscoder.java b/src/java.desktop/share/classes/javax/imageio/ImageTranscoder.java index 3ce8fc88710b59386f8b9b9028dc518f9b806aee..d2832c49a1fdd2190006304261f5bf736d1a5871 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageTranscoder.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageTranscoder.java @@ -109,7 +109,7 @@ public interface ImageTranscoder { * {@code null} if the plug-in does not provide metadata * encoding capabilities. * - * @exception IllegalArgumentException if {@code inData} is + * @throws IllegalArgumentException if {@code inData} is * {@code null}. */ IIOMetadata convertStreamMetadata(IIOMetadata inData, @@ -142,7 +142,7 @@ public interface ImageTranscoder { * or {@code null} if the plug-in does not provide * metadata encoding capabilities. * - * @exception IllegalArgumentException if either of + * @throws IllegalArgumentException if either of * {@code inData} or {@code imageType} is * {@code null}. */ diff --git a/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java b/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java index e328d7499bcd28be7794db995a9c1cfc5116a9d0..b94b7709d2bf0cdaa8473c3c877583f978a8e917 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java @@ -90,9 +90,9 @@ public class ImageTypeSpecifier { * @param colorModel a {@code ColorModel}. * @param sampleModel a {@code SampleModel}. * - * @exception IllegalArgumentException if either parameter is + * @throws IllegalArgumentException if either parameter is * {@code null}. - * @exception IllegalArgumentException if {@code sampleModel} + * @throws IllegalArgumentException if {@code sampleModel} * is not compatible with {@code colorModel}. */ public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel) { @@ -120,7 +120,7 @@ public class ImageTypeSpecifier { * * @param image a {@code RenderedImage}. * - * @exception IllegalArgumentException if the argument is + * @throws IllegalArgumentException if the argument is * {@code null}. */ public ImageTypeSpecifier(RenderedImage image) { @@ -208,13 +208,13 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code colorSpace} + * @throws IllegalArgumentException if {@code colorSpace} * is {@code null}. - * @exception IllegalArgumentException if {@code colorSpace} + * @throws IllegalArgumentException if {@code colorSpace} * is not of type {@code TYPE_RGB}. - * @exception IllegalArgumentException if no mask has at least 1 + * @throws IllegalArgumentException if no mask has at least 1 * bit set. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code transferType} if not one of * {@code DataBuffer.TYPE_BYTE}, * {@code DataBuffer.TYPE_USHORT}, or @@ -375,13 +375,13 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code colorSpace} + * @throws IllegalArgumentException if {@code colorSpace} * is {@code null}. - * @exception IllegalArgumentException if {@code bandOffsets} + * @throws IllegalArgumentException if {@code bandOffsets} * is {@code null}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the legal {@code DataBuffer.TYPE_*} constants. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code bandOffsets.length} does not equal the number of * color space components, plus 1 if {@code hasAlpha} is * {@code true}. @@ -525,19 +525,19 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code colorSpace} + * @throws IllegalArgumentException if {@code colorSpace} * is {@code null}. - * @exception IllegalArgumentException if {@code bankIndices} + * @throws IllegalArgumentException if {@code bankIndices} * is {@code null}. - * @exception IllegalArgumentException if {@code bandOffsets} + * @throws IllegalArgumentException if {@code bandOffsets} * is {@code null}. - * @exception IllegalArgumentException if the lengths of + * @throws IllegalArgumentException if the lengths of * {@code bankIndices} and {@code bandOffsets} differ. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code bandOffsets.length} does not equal the number of * color space components, plus 1 if {@code hasAlpha} is * {@code true}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the legal {@code DataBuffer.TYPE_*} constants. */ public static ImageTypeSpecifier @@ -661,13 +661,13 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * not one of 1, 2, 4, 8, or 16. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of {@code DataBuffer.TYPE_BYTE}, * {@code DataBuffer.TYPE_SHORT}, or * {@code DataBuffer.TYPE_USHORT}. - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * larger than the bit size of the given {@code dataType}. */ public static ImageTypeSpecifier @@ -697,13 +697,13 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * not one of 1, 2, 4, 8, or 16. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of {@code DataBuffer.TYPE_BYTE}, * {@code DataBuffer.TYPE_SHORT}, or * {@code DataBuffer.TYPE_USHORT}. - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * larger than the bit size of the given {@code dataType}. */ public static ImageTypeSpecifier @@ -822,23 +822,23 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code redLUT} is + * @throws IllegalArgumentException if {@code redLUT} is * {@code null}. - * @exception IllegalArgumentException if {@code greenLUT} is + * @throws IllegalArgumentException if {@code greenLUT} is * {@code null}. - * @exception IllegalArgumentException if {@code blueLUT} is + * @throws IllegalArgumentException if {@code blueLUT} is * {@code null}. - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * not one of 1, 2, 4, 8, or 16. - * @exception IllegalArgumentException if the + * @throws IllegalArgumentException if the * non-{@code null} LUT parameters do not have lengths of * exactly {@code 1 << bits}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of {@code DataBuffer.TYPE_BYTE}, * {@code DataBuffer.TYPE_SHORT}, * {@code DataBuffer.TYPE_USHORT}, * or {@code DataBuffer.TYPE_INT}. - * @exception IllegalArgumentException if {@code bits} is + * @throws IllegalArgumentException if {@code bits} is * larger than the bit size of the given {@code dataType}. */ public static ImageTypeSpecifier @@ -867,7 +867,7 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code bufferedImageType} is not one of the standard * types, or is equal to {@code TYPE_CUSTOM}. * @@ -908,7 +908,7 @@ public class ImageTypeSpecifier { * @return an {@code ImageTypeSpecifier} with the desired * characteristics. * - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. */ public static @@ -985,7 +985,7 @@ public class ImageTypeSpecifier { * * @return an int specifying a number of bits. * - * @exception IllegalArgumentException if {@code band} is + * @throws IllegalArgumentException if {@code band} is * negative or greater than the largest band index. */ public int getBitsPerBand(int band) { @@ -1017,9 +1017,9 @@ public class ImageTypeSpecifier { * * @return a {@code SampleModel} with the given dimensions. * - * @exception IllegalArgumentException if either {@code width} or + * @throws IllegalArgumentException if either {@code width} or * {@code height} are negative or zero. - * @exception IllegalArgumentException if the product of + * @throws IllegalArgumentException if the product of * {@code width} and {@code height} is greater than * {@code Integer.MAX_VALUE} */ @@ -1051,9 +1051,9 @@ public class ImageTypeSpecifier { * * @return a new {@code BufferedImage} * - * @exception IllegalArgumentException if either {@code width} or + * @throws IllegalArgumentException if either {@code width} or * {@code height} are negative or zero. - * @exception IllegalArgumentException if the product of + * @throws IllegalArgumentException if the product of * {@code width} and {@code height} is greater than * {@code Integer.MAX_VALUE}, or if the number of array * elements needed to store the image is greater than diff --git a/src/java.desktop/share/classes/javax/imageio/ImageWriteParam.java b/src/java.desktop/share/classes/javax/imageio/ImageWriteParam.java index cbaa5781271616e0009d1be73822cc8de1b88cf2..482730ba888616035eb6cbc9a383136d16f7abd9 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageWriteParam.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageWriteParam.java @@ -474,9 +474,9 @@ public class ImageWriteParam extends IIOParam { * * @param mode The mode to use for tiling. * - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteTiles} returns {@code false}. - * @exception IllegalArgumentException if {@code mode} is not + * @throws IllegalArgumentException if {@code mode} is not * one of the modes listed above. * * @see #setTiling @@ -501,7 +501,7 @@ public class ImageWriteParam extends IIOParam { * * @return the current tiling mode. * - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteTiles} returns {@code false}. * * @see #setTilingMode @@ -530,7 +530,7 @@ public class ImageWriteParam extends IIOParam { *

    If no array is specified on the constructor, but tiling is * allowed, then this method returns {@code null}. * - * @exception UnsupportedOperationException if the plug-in does + * @throws UnsupportedOperationException if the plug-in does * not support tiling. * * @return an array of {@code Dimension}s with an even length @@ -559,16 +559,16 @@ public class ImageWriteParam extends IIOParam { * @param tileGridXOffset the horizontal offset of the tile grid. * @param tileGridYOffset the vertical offset of the tile grid. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support grid offsets, and the grid offsets are not both zero. - * @exception IllegalArgumentException if the tile size is not + * @throws IllegalArgumentException if the tile size is not * within one of the allowable ranges returned by * {@code getPreferredTileSizes}. - * @exception IllegalArgumentException if {@code tileWidth} + * @throws IllegalArgumentException if {@code tileWidth} * or {@code tileHeight} is less than or equal to 0. * * @see #canWriteTiles @@ -630,9 +630,9 @@ public class ImageWriteParam extends IIOParam { * {@code tileGridXOffset}, and * {@code tileGridYOffset} to {@code 0}. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. * * @see #setTiling(int, int, int, int) @@ -658,11 +658,11 @@ public class ImageWriteParam extends IIOParam { * * @return the tile width to be used for encoding. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the tiling parameters have + * @throws IllegalStateException if the tiling parameters have * not been set. * * @see #setTiling(int, int, int, int) @@ -688,11 +688,11 @@ public class ImageWriteParam extends IIOParam { * * @return the tile height to be used for encoding. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the tiling parameters have + * @throws IllegalStateException if the tiling parameters have * not been set. * * @see #setTiling(int, int, int, int) @@ -718,11 +718,11 @@ public class ImageWriteParam extends IIOParam { * * @return the tile grid X offset to be used for encoding. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the tiling parameters have + * @throws IllegalStateException if the tiling parameters have * not been set. * * @see #setTiling(int, int, int, int) @@ -748,11 +748,11 @@ public class ImageWriteParam extends IIOParam { * * @return the tile grid Y offset to be used for encoding. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support tiling. - * @exception IllegalStateException if the tiling mode is not + * @throws IllegalStateException if the tiling mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the tiling parameters have + * @throws IllegalStateException if the tiling parameters have * not been set. * * @see #setTiling(int, int, int, int) @@ -818,9 +818,9 @@ public class ImageWriteParam extends IIOParam { * @param mode The mode for setting progression in the output * stream. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support progressive encoding. - * @exception IllegalArgumentException if {@code mode} is not + * @throws IllegalArgumentException if {@code mode} is not * one of the modes listed above. * * @see #getProgressiveMode @@ -846,7 +846,7 @@ public class ImageWriteParam extends IIOParam { * * @return the current mode for progressive encoding. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support progressive encoding. * * @see #setProgressiveMode @@ -902,9 +902,9 @@ public class ImageWriteParam extends IIOParam { * @param mode The mode for setting compression in the output * stream. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression, or does not support the requested mode. - * @exception IllegalArgumentException if {@code mode} is not + * @throws IllegalArgumentException if {@code mode} is not * one of the modes listed above. * * @see #getCompressionMode @@ -929,7 +929,7 @@ public class ImageWriteParam extends IIOParam { * * @return the current compression mode. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. * * @see #setCompressionMode @@ -965,7 +965,7 @@ public class ImageWriteParam extends IIOParam { * (non-localized) names of available compression types, or * {@code null}. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. */ public String[] getCompressionTypes() { @@ -998,13 +998,13 @@ public class ImageWriteParam extends IIOParam { * by {@code getCompressionTypes}, or {@code null} to * remove any previous setting. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception UnsupportedOperationException if there are no + * @throws UnsupportedOperationException if there are no * settable compression types. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code compressionType} is non-{@code null} but is not * one of the values returned by {@code getCompressionTypes}. * @@ -1059,9 +1059,9 @@ public class ImageWriteParam extends IIOParam { * @return the current compression type as a {@code String}, * or {@code null} if no type is set. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. * * @see #setCompressionType @@ -1086,9 +1086,9 @@ public class ImageWriteParam extends IIOParam { * instance variable {@code compressionQuality} to * {@code 1.0F}. * - * @exception UnsupportedOperationException if the plug-in does not + * @throws UnsupportedOperationException if the plug-in does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. * * @see #setCompressionType @@ -1122,11 +1122,11 @@ public class ImageWriteParam extends IIOParam { * @return a {@code String} containing a localized version of * the name of the current compression type. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if no compression type is set. + * @throws IllegalStateException if no compression type is set. */ public String getLocalizedCompressionTypeName() { if (!canWriteCompressed()) { @@ -1162,11 +1162,11 @@ public class ImageWriteParam extends IIOParam { * @return {@code true} if the current compression type is * lossless. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. */ @@ -1218,14 +1218,14 @@ public class ImageWriteParam extends IIOParam { * @param quality a {@code float} between {@code 0} and * {@code 1} indicating the desired quality level. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. - * @exception IllegalArgumentException if {@code quality} is + * @throws IllegalArgumentException if {@code quality} is * not between {@code 0} and {@code 1}, inclusive. * * @see #getCompressionQuality @@ -1264,11 +1264,11 @@ public class ImageWriteParam extends IIOParam { * * @return the current compression quality setting. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. * @@ -1317,14 +1317,14 @@ public class ImageWriteParam extends IIOParam { * @return an estimate of the compressed bit rate, or * {@code -1.0F} if no estimate is available. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. - * @exception IllegalArgumentException if {@code quality} is + * @throws IllegalArgumentException if {@code quality} is * not between {@code 0} and {@code 1}, inclusive. */ public float getBitRate(float quality) { @@ -1389,11 +1389,11 @@ public class ImageWriteParam extends IIOParam { * @return an array of {@code String}s containing localized * descriptions of the compression quality levels. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. * @@ -1442,11 +1442,11 @@ public class ImageWriteParam extends IIOParam { * by the {@code String}s from * {@code getCompressionQualityDescriptions}. * - * @exception UnsupportedOperationException if the writer does not + * @throws UnsupportedOperationException if the writer does not * support compression. - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. - * @exception IllegalStateException if the set of legal + * @throws IllegalStateException if the set of legal * compression types is non-{@code null} and the current * compression type is {@code null}. * diff --git a/src/java.desktop/share/classes/javax/imageio/ImageWriter.java b/src/java.desktop/share/classes/javax/imageio/ImageWriter.java index 8723c50773e527d22039c02b26ab9135a95a477c..a688d9aea911bf4af262051e7afa87547a3ec173 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageWriter.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageWriter.java @@ -194,7 +194,7 @@ public abstract class ImageWriter implements ImageTranscoder { * @param output the {@code ImageOutputStream} or other * {@code Object} to use for future writing. * - * @exception IllegalArgumentException if {@code output} is + * @throws IllegalArgumentException if {@code output} is * not an instance of one of the classes returned by the * originating service provider's {@code getOutputTypes} * method. @@ -276,7 +276,7 @@ public abstract class ImageWriter implements ImageTranscoder { * @param locale the desired {@code Locale}, or * {@code null}. * - * @exception IllegalArgumentException if {@code locale} is + * @throws IllegalArgumentException if {@code locale} is * non-{@code null} but is not one of the values returned by * {@code getAvailableLocales}. * @@ -561,14 +561,14 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if {@code image} + * @throws UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public abstract void write(IIOMetadata streamMetadata, IIOImage image, @@ -582,14 +582,14 @@ public abstract class ImageWriter implements ImageTranscoder { * @param image an {@code IIOImage} object containing an * image, thumbnails, and metadata to be written. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. - * @exception UnsupportedOperationException if {@code image} + * @throws UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void write(IIOImage image) throws IOException { write(null, image, null); @@ -603,11 +603,11 @@ public abstract class ImageWriter implements ImageTranscoder { * * @param image a {@code RenderedImage} to be written. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void write(RenderedImage image) throws IOException { write(null, new IIOImage(image, null, null), null); @@ -671,11 +671,11 @@ public abstract class ImageWriter implements ImageTranscoder { * * @param streamMetadata A stream metadata object, or {@code null}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. - * @exception IOException if an error occurs writing the stream + * @throws IOException if an error occurs writing the stream * metadata. */ public void prepareWriteSequence(IIOMetadata streamMetadata) @@ -732,16 +732,16 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set, or {@code prepareWriteSequence} has not been called. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. - * @exception UnsupportedOperationException if {@code image} + * @throws UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException { @@ -767,11 +767,11 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null}, and otherwise throws an * {@code UnsupportedOperationException}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set, or {@code prepareWriteSequence} has not been called. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void endWriteSequence() throws IOException { unsupported(); @@ -790,9 +790,9 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if replacement of stream metadata is * allowed. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IOException if an I/O error occurs during the query. + * @throws IOException if an I/O error occurs during the query. */ public boolean canReplaceStreamMetadata() throws IOException { if (getOutput() == null) { @@ -821,12 +821,12 @@ public abstract class ImageWriter implements ImageTranscoder { * @param streamMetadata an {@code IIOMetadata} object representing * stream metadata, or {@code null} to use default values. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if the + * @throws UnsupportedOperationException if the * {@code canReplaceStreamMetadata} returns * {@code false}. modes do not include - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void replaceStreamMetadata(IIOMetadata streamMetadata) throws IOException { @@ -856,13 +856,13 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if the image metadata of the given * image can be replaced. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IndexOutOfBoundsException if the writer supports + * @throws IndexOutOfBoundsException if the writer supports * image metadata replacement in general, but * {@code imageIndex} is less than 0 or greater than the * largest available index. - * @exception IOException if an I/O error occurs during the query. + * @throws IOException if an I/O error occurs during the query. */ public boolean canReplaceImageMetadata(int imageIndex) throws IOException { @@ -889,14 +889,14 @@ public abstract class ImageWriter implements ImageTranscoder { * @param imageMetadata an {@code IIOMetadata} object * representing image metadata, or {@code null}. * - * @exception IllegalStateException if the output has not been + * @throws IllegalStateException if the output has not been * set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canReplaceImageMetadata} returns * {@code false}. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is less than 0 or greater than the largest available index. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void replaceImageMetadata(int imageIndex, IIOMetadata imageMetadata) @@ -929,12 +929,12 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if an image may be inserted at the * given index. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IndexOutOfBoundsException if the writer supports + * @throws IndexOutOfBoundsException if the writer supports * image insertion in general, but {@code imageIndex} is less * than -1 or greater than the largest available index. - * @exception IOException if an I/O error occurs during the query. + * @throws IOException if an I/O error occurs during the query. */ public boolean canInsertImage(int imageIndex) throws IOException { if (getOutput() == null) { @@ -978,18 +978,18 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canInsertImage(imageIndex)} returns {@code false}. - * @exception IllegalArgumentException if {@code image} is + * @throws IllegalArgumentException if {@code image} is * {@code null}. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is less than -1 or greater than the largest available index. - * @exception UnsupportedOperationException if {@code image} + * @throws UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. - * @exception IOException if an error occurs during writing. + * @throws IOException if an error occurs during writing. */ public void writeInsert(int imageIndex, IIOImage image, @@ -1019,12 +1019,12 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if it is possible to remove the given * image. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception IndexOutOfBoundsException if the writer supports + * @throws IndexOutOfBoundsException if the writer supports * image removal in general, but {@code imageIndex} is less * than 0 or greater than the largest available index. - * @exception IOException if an I/O error occurs during the + * @throws IOException if an I/O error occurs during the * query. */ public boolean canRemoveImage(int imageIndex) throws IOException { @@ -1050,13 +1050,13 @@ public abstract class ImageWriter implements ImageTranscoder { * * @param imageIndex the index of the image to be removed. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canRemoveImage(imageIndex)} returns {@code false}. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is less than 0 or greater than the largest available index. - * @exception IOException if an I/O error occurs during the + * @throws IOException if an I/O error occurs during the * removal. */ public void removeImage(int imageIndex) throws IOException { @@ -1082,9 +1082,9 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if the writing of complete image * stream with contents to be defined later is supported. * - * @exception IllegalStateException if the output has not been + * @throws IllegalStateException if the output has not been * set. - * @exception IOException if an I/O error occurs during the + * @throws IOException if an I/O error occurs during the * query. */ public boolean canWriteEmpty() throws IOException { @@ -1144,23 +1144,23 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteEmpty} returns {@code false}. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareWriteEmpty} has been made without a * corresponding call to {@code endWriteEmpty}. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareInsertEmpty} has been made without a * corresponding call to {@code endInsertEmpty}. - * @exception IllegalArgumentException if {@code imageType} + * @throws IllegalArgumentException if {@code imageType} * is {@code null} or {@code thumbnails} contains * {@code null} references or objects other than * {@code BufferedImage}s. - * @exception IllegalArgumentException if width or height are less + * @throws IllegalArgumentException if width or height are less * than 1. - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void prepareWriteEmpty(IIOMetadata streamMetadata, ImageTypeSpecifier imageType, @@ -1183,21 +1183,21 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null}, and otherwise throws an * {@code UnsupportedOperationException}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteEmpty(imageIndex)} returns * {@code false}. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareWriteEmpty} without a corresponding call to * {@code endWriteEmpty} has not been made. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareInsertEmpty} without a corresponding call to * {@code endInsertEmpty} has been made. - * @exception IllegalStateException if a call to + * @throws IllegalStateException if a call to * {@code prepareReiplacePixels} has been made without a * matching call to {@code endReplacePixels}. - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void endWriteEmpty() throws IOException { if (getOutput() == null) { @@ -1231,12 +1231,12 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if an empty image may be inserted at * the given index. * - * @exception IllegalStateException if the output has not been + * @throws IllegalStateException if the output has not been * set. - * @exception IndexOutOfBoundsException if the writer supports + * @throws IndexOutOfBoundsException if the writer supports * empty image insertion in general, but {@code imageIndex} * is less than -1 or greater than the largest available index. - * @exception IOException if an I/O error occurs during the + * @throws IOException if an I/O error occurs during the * query. */ public boolean canInsertEmpty(int imageIndex) throws IOException { @@ -1301,26 +1301,26 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canInsertEmpty(imageIndex)} returns * {@code false}. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is less than -1 or greater than the largest available index. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareInsertEmpty} has been made without a * corresponding call to {@code endInsertEmpty}. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareWriteEmpty} has been made without a * corresponding call to {@code endWriteEmpty}. - * @exception IllegalArgumentException if {@code imageType} + * @throws IllegalArgumentException if {@code imageType} * is {@code null} or {@code thumbnails} contains * {@code null} references or objects other than * {@code BufferedImage}s. - * @exception IllegalArgumentException if width or height are less + * @throws IllegalArgumentException if width or height are less * than 1. - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void prepareInsertEmpty(int imageIndex, ImageTypeSpecifier imageType, @@ -1340,21 +1340,21 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null}, and otherwise throws an * {@code UnsupportedOperationException}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canInsertEmpty(imageIndex)} returns * {@code false}. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareInsertEmpty} without a corresponding call to * {@code endInsertEmpty} has not been made. - * @exception IllegalStateException if a previous call to + * @throws IllegalStateException if a previous call to * {@code prepareWriteEmpty} without a corresponding call to * {@code endWriteEmpty} has been made. - * @exception IllegalStateException if a call to + * @throws IllegalStateException if a call to * {@code prepareReplacePixels} has been made without a * matching call to {@code endReplacePixels}. - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void endInsertEmpty() throws IOException { unsupported(); @@ -1382,12 +1382,12 @@ public abstract class ImageWriter implements ImageTranscoder { * @return {@code true} if the pixels of the given * image can be replaced. * - * @exception IllegalStateException if the output has not been + * @throws IllegalStateException if the output has not been * set. - * @exception IndexOutOfBoundsException if the writer supports + * @throws IndexOutOfBoundsException if the writer supports * pixel replacement in general, but {@code imageIndex} is * less than 0 or greater than the largest available index. - * @exception IOException if an I/O error occurs during the query. + * @throws IOException if an I/O error occurs during the query. */ public boolean canReplacePixels(int imageIndex) throws IOException { if (getOutput() == null) { @@ -1415,20 +1415,20 @@ public abstract class ImageWriter implements ImageTranscoder { * @param region a {@code Rectangle} that will be used to clip * future pixel regions. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. - * @exception IndexOutOfBoundsException if {@code imageIndex} + * @throws IndexOutOfBoundsException if {@code imageIndex} * is less than 0 or greater than the largest available index. - * @exception IllegalStateException if there is a previous call to + * @throws IllegalStateException if there is a previous call to * {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels} (i.e., nesting is not * allowed). - * @exception IllegalArgumentException if {@code region} is + * @throws IllegalArgumentException if {@code region} is * {@code null} or has a width or height less than 1. - * @exception IOException if an I/O error occurs during the + * @throws IOException if an I/O error occurs during the * preparation. */ public void prepareReplacePixels(int imageIndex, @@ -1471,22 +1471,22 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. - * @exception IllegalStateException if there is no previous call to + * @throws IllegalStateException if there is no previous call to * {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. - * @exception IllegalArgumentException if any of the following are true: + * @throws IllegalArgumentException if any of the following are true: *

      *
    • {@code image} is {@code null}. *
    • the intersected region does not contain at least one pixel. *
    • the layout of {@code image} does not match, or this * writer cannot convert it to, the existing image layout. *
    - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void replacePixels(RenderedImage image, ImageWriteParam param) throws IOException { @@ -1529,24 +1529,24 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null} to use a default * {@code ImageWriteParam}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. - * @exception IllegalStateException if there is no previous call to + * @throws IllegalStateException if there is no previous call to * {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canWriteRasters} returns {@code false}. - * @exception IllegalArgumentException if any of the following are true: + * @throws IllegalArgumentException if any of the following are true: *
      *
    • {@code raster} is {@code null}. *
    • the intersected region does not contain at least one pixel. *
    • the layout of {@code raster} does not match, or this * writer cannot convert it to, the existing image layout. *
    - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void replacePixels(Raster raster, ImageWriteParam param) throws IOException { @@ -1565,15 +1565,15 @@ public abstract class ImageWriter implements ImageTranscoder { * {@code null}, and otherwise throws an * {@code UnsupportedOperationException}. * - * @exception IllegalStateException if the output has not + * @throws IllegalStateException if the output has not * been set. - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. - * @exception IllegalStateException if there is no previous call + * @throws IllegalStateException if there is no previous call * to {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. - * @exception IOException if an I/O error occurs during writing. + * @throws IOException if an I/O error occurs during writing. */ public void endReplacePixels() throws IOException { unsupported(); @@ -1886,7 +1886,7 @@ public abstract class ImageWriter implements ImageTranscoder { * occurred. * @param warning the warning message. * - * @exception IllegalArgumentException if {@code warning} + * @throws IllegalArgumentException if {@code warning} * is {@code null}. */ protected void processWarningOccurred(int imageIndex, @@ -1921,15 +1921,15 @@ public abstract class ImageWriter implements ImageTranscoder { * @param keyword the keyword used to index the warning message * within the set of {@code ResourceBundle}s. * - * @exception IllegalArgumentException if {@code baseName} + * @throws IllegalArgumentException if {@code baseName} * is {@code null}. - * @exception IllegalArgumentException if {@code keyword} + * @throws IllegalArgumentException if {@code keyword} * is {@code null}. - * @exception IllegalArgumentException if no appropriate + * @throws IllegalArgumentException if no appropriate * {@code ResourceBundle} may be located. - * @exception IllegalArgumentException if the named resource is + * @throws IllegalArgumentException if the named resource is * not found in the located {@code ResourceBundle}. - * @exception IllegalArgumentException if the object retrieved + * @throws IllegalArgumentException if the object retrieved * from the {@code ResourceBundle} is not a * {@code String}. */ diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java index 9952544b48745c3dd87de2d630f25fe3efa72247..3954f886f47f7ecab728e54c6ad4575dbd4483b6 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java @@ -165,9 +165,9 @@ public abstract class IIOMetadata { * indicating the class names of any additional formats supported by * this object, or {@code null} if there are none. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code extraMetadataFormatNames} has length 0. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code extraMetadataFormatNames} and * {@code extraMetadataFormatClassNames} are neither both * {@code null}, nor of the same length. @@ -368,10 +368,10 @@ public abstract class IIOMetadata { * * @return an {@code IIOMetadataFormat} object. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not one of the names recognized by * the plug-in. - * @exception IllegalStateException if the class corresponding to + * @throws IllegalStateException if the class corresponding to * the format name cannot be loaded. */ public IIOMetadataFormat getMetadataFormat(String formatName) { @@ -452,7 +452,7 @@ public abstract class IIOMetadata { * @return an XML DOM {@code Node} object forming the * root of a tree. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not one of the names returned by * {@code getMetadataFormatNames}. * @@ -481,13 +481,13 @@ public abstract class IIOMetadata { * @param root an XML DOM {@code Node} object forming the * root of a tree. * - * @exception IllegalStateException if this object is read-only. - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalStateException if this object is read-only. + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not one of the names returned by * {@code getMetadataFormatNames}. - * @exception IllegalArgumentException if {@code root} is + * @throws IllegalArgumentException if {@code root} is * {@code null}. - * @exception IIOInvalidTreeException if the tree cannot be parsed + * @throws IIOInvalidTreeException if the tree cannot be parsed * successfully using the rules of the given format. * * @see #getMetadataFormatNames @@ -731,13 +731,13 @@ public abstract class IIOMetadata { * @param root an XML DOM {@code Node} object forming the * root of a tree. * - * @exception IllegalStateException if this object is read-only. - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalStateException if this object is read-only. + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not one of the names returned by * {@code getMetadataFormatNames}. - * @exception IllegalArgumentException if {@code root} is + * @throws IllegalArgumentException if {@code root} is * {@code null}. - * @exception IIOInvalidTreeException if the tree cannot be parsed + * @throws IIOInvalidTreeException if the tree cannot be parsed * successfully using the rules of the given format. * * @see #getMetadataFormatNames @@ -757,7 +757,7 @@ public abstract class IIOMetadata { * Note that there are many possible default values, depending on * how the object was created. * - * @exception IllegalStateException if this object is read-only. + * @throws IllegalStateException if this object is read-only. * * @see javax.imageio.ImageReader#getStreamMetadata * @see javax.imageio.ImageReader#getImageMetadata @@ -873,7 +873,7 @@ public abstract class IIOMetadata { * * @return {@code true} if the controller completed normally. * - * @exception IllegalStateException if there is no controller + * @throws IllegalStateException if there is no controller * currently installed. * * @see IIOMetadataController diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataController.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataController.java index ddf105763f0a59e326945389272ef48433e717cb..88f8727aad5cf90bd3ddbf1ede445397666ca22c 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataController.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataController.java @@ -79,7 +79,7 @@ public interface IIOMetadataController { * @return {@code true} if the {@code IIOMetadata} has been * modified, {@code false} otherwise. * - * @exception IllegalArgumentException if {@code metadata} is + * @throws IllegalArgumentException if {@code metadata} is * {@code null} or is not an instance of the correct class. */ boolean activate(IIOMetadata metadata); diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java index 797ecc5618084d026d42a7645b1761b4d6005f8c..b0cd40b6f6ebd458e8e49dba8d66150bb9785b07 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java @@ -319,10 +319,10 @@ public interface IIOMetadataFormat { * * @return an {@code int}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element does + * @throws IllegalArgumentException if the named element does * not have a child policy of {@code CHILD_POLICY_REPEAT}. */ int getElementMinChildren(String elementName); @@ -339,10 +339,10 @@ public interface IIOMetadataFormat { * * @return an {@code int}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element does + * @throws IllegalArgumentException if the named element does * not have a child policy of {@code CHILD_POLICY_REPEAT}. */ int getElementMaxChildren(String elementName); @@ -362,7 +362,7 @@ public interface IIOMetadataFormat { * * @return the element description. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. */ String getElementDescription(String elementName, Locale locale); @@ -378,7 +378,7 @@ public interface IIOMetadataFormat { * * @return one of the {@code CHILD_POLICY_*} constants. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. */ @@ -394,7 +394,7 @@ public interface IIOMetadataFormat { * * @return an array of {@code String}s, or null. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. */ @@ -410,7 +410,7 @@ public interface IIOMetadataFormat { * * @return an array of {@code String}s. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. */ @@ -428,10 +428,10 @@ public interface IIOMetadataFormat { * * @return one of the {@code VALUE_*} constants. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. */ @@ -450,10 +450,10 @@ public interface IIOMetadataFormat { * * @return one of the {@code DATATYPE_*} constants. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. */ @@ -468,10 +468,10 @@ public interface IIOMetadataFormat { * * @return {@code true} if the attribute must be present. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. */ @@ -489,10 +489,10 @@ public interface IIOMetadataFormat { * @return a {@code String} containing the default value, or * {@code null}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. */ @@ -510,13 +510,13 @@ public interface IIOMetadataFormat { * * @return an array of {@code String}s. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. - * @exception IllegalArgumentException if the given attribute is + * @throws IllegalArgumentException if the given attribute is * not defined as an enumeration. */ String[] getAttributeEnumerations(String elementName, String attrName); @@ -537,13 +537,13 @@ public interface IIOMetadataFormat { * @return a {@code String} containing the smallest legal * value for the attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. - * @exception IllegalArgumentException if the given attribute is + * @throws IllegalArgumentException if the given attribute is * not defined as a range. */ String getAttributeMinValue(String elementName, String attrName); @@ -565,13 +565,13 @@ public interface IIOMetadataFormat { * @return a {@code String} containing the largest legal * value for the attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. - * @exception IllegalArgumentException if the given attribute is + * @throws IllegalArgumentException if the given attribute is * not defined as a range. */ String getAttributeMaxValue(String elementName, String attrName); @@ -590,13 +590,13 @@ public interface IIOMetadataFormat { * @return the smallest legal number of list items for the * attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. - * @exception IllegalArgumentException if the given attribute is + * @throws IllegalArgumentException if the given attribute is * not defined as a list. */ int getAttributeListMinLength(String elementName, String attrName); @@ -617,13 +617,13 @@ public interface IIOMetadataFormat { * @return the largest legal number of list items for the * attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. - * @exception IllegalArgumentException if the given attribute is + * @throws IllegalArgumentException if the given attribute is * not defined as a list. */ int getAttributeListMaxLength(String elementName, String attrName); @@ -644,9 +644,9 @@ public interface IIOMetadataFormat { * * @return the attribute description. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. */ @@ -671,7 +671,7 @@ public interface IIOMetadataFormat { * * @return one of the {@code VALUE_*} constants. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. * @@ -696,10 +696,10 @@ public interface IIOMetadataFormat { * * @return a {@code Class} object. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). */ @@ -714,10 +714,10 @@ public interface IIOMetadataFormat { * * @return an {@code Object}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). */ @@ -739,13 +739,13 @@ public interface IIOMetadataFormat { * * @return an array of {@code Object}s. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). - * @exception IllegalArgumentException if the {@code Object} + * @throws IllegalArgumentException if the {@code Object} * is not defined as an enumeration. */ Object[] getObjectEnumerations(String elementName); @@ -762,13 +762,13 @@ public interface IIOMetadataFormat { * * @return the smallest legal value for the attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). - * @exception IllegalArgumentException if the {@code Object} + * @throws IllegalArgumentException if the {@code Object} * is not defined as a range. */ Comparable getObjectMinValue(String elementName); @@ -785,13 +785,13 @@ public interface IIOMetadataFormat { * * @param elementName the name of the element being queried. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). - * @exception IllegalArgumentException if the {@code Object} + * @throws IllegalArgumentException if the {@code Object} * is not defined as a range. */ Comparable getObjectMaxValue(String elementName); @@ -808,13 +808,13 @@ public interface IIOMetadataFormat { * @return the smallest valid array length for the * {@code Object} reference. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). - * @exception IllegalArgumentException if the {@code Object} is not + * @throws IllegalArgumentException if the {@code Object} is not * an array. */ int getObjectArrayMinLength(String elementName); @@ -832,13 +832,13 @@ public interface IIOMetadataFormat { * @return the largest valid array length for the * {@code Object} reference. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null} or is not a legal element name for this * format. - * @exception IllegalArgumentException if the named element cannot + * @throws IllegalArgumentException if the named element cannot * contain an object value (i.e., if * {@code getObjectValueType(elementName) == VALUE_NONE}). - * @exception IllegalArgumentException if the {@code Object} is not + * @throws IllegalArgumentException if the {@code Object} is not * an array. */ int getObjectArrayMaxLength(String elementName); diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java index 8b5de4089efb912f3fc255a6361651db6fd075d0..d81b0df3c876ffea34e2772ba1321e6f277239e4 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java @@ -160,9 +160,9 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param childPolicy one of the {@code CHILD_POLICY_*} constants, * other than {@code CHILD_POLICY_REPEAT}. * - * @exception IllegalArgumentException if {@code rootName} is + * @throws IllegalArgumentException if {@code rootName} is * {@code null}. - * @exception IllegalArgumentException if {@code childPolicy} is + * @throws IllegalArgumentException if {@code childPolicy} is * not one of the predefined constants. */ public IIOMetadataFormatImpl(String rootName, @@ -196,9 +196,9 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param minChildren the minimum number of children of the node. * @param maxChildren the maximum number of children of the node. * - * @exception IllegalArgumentException if {@code rootName} is + * @throws IllegalArgumentException if {@code rootName} is * {@code null}. - * @exception IllegalArgumentException if {@code minChildren} + * @throws IllegalArgumentException if {@code minChildren} * is negative or larger than {@code maxChildren}. */ public IIOMetadataFormatImpl(String rootName, @@ -236,7 +236,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param resourceBaseName a {@code String} containing the new * base name. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code resourceBaseName} is {@code null}. * * @see #getResourceBaseName @@ -307,10 +307,10 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * constants, other than {@code CHILD_POLICY_REPEAT}, * indicating the child policy of the new element. * - * @exception IllegalArgumentException if {@code parentName} + * @throws IllegalArgumentException if {@code parentName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code childPolicy} + * @throws IllegalArgumentException if {@code childPolicy} * is not one of the predefined constants. */ protected void addElement(String elementName, @@ -344,10 +344,10 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param minChildren the minimum number of children of the node. * @param maxChildren the maximum number of children of the node. * - * @exception IllegalArgumentException if {@code parentName} + * @throws IllegalArgumentException if {@code parentName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code minChildren} + * @throws IllegalArgumentException if {@code minChildren} * is negative or larger than {@code maxChildren}. */ protected void addElement(String elementName, @@ -383,10 +383,10 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param elementName the name of the element to be added as a * child. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code parentName} + * @throws IllegalArgumentException if {@code parentName} * is {@code null}, or is not a legal element name for this * format. */ @@ -429,12 +429,12 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param defaultValue the default value for the attribute, or * {@code null}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the predefined constants. */ protected void addAttribute(String elementName, @@ -476,19 +476,19 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * {@code String}s containing the legal values for the * attribute. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the predefined constants. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} is {@code null}. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} does not contain at least one * entry. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} contains an element that is not a * {@code String} or is {@code null}. */ @@ -556,12 +556,12 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param maxInclusive {@code true} if {@code maxValue} * is inclusive. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the predefined constants. */ protected void addAttribute(String elementName, @@ -612,14 +612,14 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param listMinLength the smallest legal number of list items. * @param listMaxLength the largest legal number of list items. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null}. - * @exception IllegalArgumentException if {@code dataType} is + * @throws IllegalArgumentException if {@code dataType} is * not one of the predefined constants. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code listMinLength} is negative or larger than * {@code listMaxLength}. */ @@ -666,10 +666,10 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * {@code boolean}, ignored if {@code hasDefaultValue} * is {@code false}. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null}. */ protected void addBooleanAttribute(String elementName, @@ -700,7 +700,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param elementName the name of the element. * @param attrName the name of the attribute being removed. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. */ protected void removeAttribute(String elementName, String attrName) { @@ -726,7 +726,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * {@code Object} reference, or {@code null}. * @param the type of the object. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. */ protected void addObjectValue(String elementName, @@ -763,14 +763,14 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * object reference. * @param the type of the object. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} is {@code null}. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} does not contain at least one * entry. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code enumeratedValues} contains an element that is not * an instance of the class type denoted by {@code classType} * or is {@code null}. @@ -833,7 +833,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * is inclusive. * @param the type of the object. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this * format. */ @@ -880,7 +880,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * @param arrayMinLength the smallest legal length for the array. * @param arrayMaxLength the largest legal length for the array. * - * @exception IllegalArgumentException if {@code elementName} is + * @throws IllegalArgumentException if {@code elementName} is * not a legal element name for this format. */ protected void addObjectValue(String elementName, @@ -903,7 +903,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * * @param elementName the name of the element. * - * @exception IllegalArgumentException if {@code elementName} is + * @throws IllegalArgumentException if {@code elementName} is * not a legal element name for this format. */ protected void removeObjectValue(String elementName) { @@ -990,7 +990,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * * @return the element description. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. * * @see #setResourceBaseName @@ -1130,9 +1130,9 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat { * * @return the attribute description. * - * @exception IllegalArgumentException if {@code elementName} + * @throws IllegalArgumentException if {@code elementName} * is {@code null}, or is not a legal element name for this format. - * @exception IllegalArgumentException if {@code attrName} is + * @throws IllegalArgumentException if {@code attrName} is * {@code null} or is not a legal attribute name for this * element. * diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java index 227bc8dcb317f846a42d119c2d5b57054c2c9570..e57d0ba00fd80f68c22ba3f4628b884ec7da2cf7 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java @@ -464,7 +464,7 @@ public class IIOMetadataNode implements Element, NodeList { * * @return the node being inserted. * - * @exception IllegalArgumentException if {@code newChild} is + * @throws IllegalArgumentException if {@code newChild} is * {@code null}. */ public Node insertBefore(Node newChild, @@ -522,7 +522,7 @@ public class IIOMetadataNode implements Element, NodeList { * * @return the node replaced. * - * @exception IllegalArgumentException if {@code newChild} is + * @throws IllegalArgumentException if {@code newChild} is * {@code null}. */ public Node replaceChild(Node newChild, @@ -573,7 +573,7 @@ public class IIOMetadataNode implements Element, NodeList { * * @return the node removed. * - * @exception IllegalArgumentException if {@code oldChild} is + * @throws IllegalArgumentException if {@code oldChild} is * {@code null}. */ public Node removeChild(Node oldChild) { @@ -617,7 +617,7 @@ public class IIOMetadataNode implements Element, NodeList { * * @return the node added. * - * @exception IllegalArgumentException if {@code newChild} is + * @throws IllegalArgumentException if {@code newChild} is * {@code null}. */ public Node appendChild(Node newChild) { diff --git a/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageReadParam.java b/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageReadParam.java index 8904c89fff2f7d7d0b16946001a40ebd8be17412..507d2c2804115fa605627b0b7502a3858aef6a9a 100644 --- a/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageReadParam.java +++ b/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageReadParam.java @@ -113,7 +113,7 @@ public class JPEGImageReadParam extends ImageReadParam { * @param DCHuffmanTables an array of Huffman table objects. * @param ACHuffmanTables an array of Huffman table objects. * - * @exception IllegalArgumentException if any of the arguments + * @throws IllegalArgumentException if any of the arguments * is {@code null}, has more than 4 elements, or if the * numbers of DC and AC tables differ. * diff --git a/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java b/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java index 986d302decc2359057d01832124455015fb2274b..de9c077d8c7e9d4769f04fd104c93a550292793a 100644 --- a/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java +++ b/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java @@ -130,7 +130,7 @@ public class JPEGImageWriteParam extends ImageWriteParam { *

    The default implementation resets the compression quality * to {@code 0.75F}. * - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. */ public void unsetCompression() { @@ -147,7 +147,7 @@ public class JPEGImageWriteParam extends ImageWriteParam { * * @return {@code false}. * - * @exception IllegalStateException if the compression mode is not + * @throws IllegalStateException if the compression mode is not * {@code MODE_EXPLICIT}. */ public boolean isCompressionLossless() { @@ -204,7 +204,7 @@ public class JPEGImageWriteParam extends ImageWriteParam { * @param DCHuffmanTables An array of Huffman table objects. * @param ACHuffmanTables An array of Huffman table objects. * - * @exception IllegalArgumentException if any of the arguments + * @throws IllegalArgumentException if any of the arguments * is {@code null} or has more than 4 elements, or if the * numbers of DC and AC tables differ. * diff --git a/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java b/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java index f31663bfa6382772d97c166910364c607ab3d1d2..881df65993f7ef2ef84617f891e6fac1ef9f43f5 100644 --- a/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java +++ b/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java @@ -29,7 +29,7 @@ import java.util.List; /** * A class representing the extra tags found in a - * TIFF-F (RFC 2036) file. + * TIFF-F (RFC 2036) file. * * @since 9 */ diff --git a/src/java.desktop/share/classes/javax/imageio/spi/IIOServiceProvider.java b/src/java.desktop/share/classes/javax/imageio/spi/IIOServiceProvider.java index 95f0ec0edaba4f9c99c0572105a4e101debd42e3..9bb3cbac97e5d63b072c435c38805ecf83fe8df8 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/IIOServiceProvider.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/IIOServiceProvider.java @@ -65,9 +65,9 @@ public abstract class IIOServiceProvider implements RegisterableService { * @param vendorName the vendor name. * @param version a version identifier. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. */ public IIOServiceProvider(String vendorName, diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageInputStreamSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageInputStreamSpi.java index e7f7264287cd340773eb746682557463508ef7e6..fb3b8d58e31148efdc143082cfa5a442f6f676d8 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageInputStreamSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageInputStreamSpi.java @@ -79,9 +79,9 @@ public abstract class ImageInputStreamSpi extends IIOServiceProvider { * legal object type for use by the * {@code createInputStreamInstance} method. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. */ public ImageInputStreamSpi(String vendorName, @@ -159,12 +159,12 @@ public abstract class ImageInputStreamSpi extends IIOServiceProvider { * * @return an {@code ImageInputStream} instance. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * not an instance of the correct class or is {@code null}. - * @exception IllegalArgumentException if a cache file is needed + * @throws IllegalArgumentException if a cache file is needed * but {@code cacheDir} is non-{@code null} and is not a * directory. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see #getInputClass @@ -187,9 +187,9 @@ public abstract class ImageInputStreamSpi extends IIOServiceProvider { * * @return an {@code ImageInputStream} instance. * - * @exception IllegalArgumentException if {@code input} is + * @throws IllegalArgumentException if {@code input} is * not an instance of the correct class or is {@code null}. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see #getInputClass() diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageOutputStreamSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageOutputStreamSpi.java index d3cf9593d0473ce2c8a66e5719d91841fb481fc9..a8fcf7ef19f704bdb5792109188d17995b50e3f8 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageOutputStreamSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageOutputStreamSpi.java @@ -80,9 +80,9 @@ public abstract class ImageOutputStreamSpi extends IIOServiceProvider { * legal object type for use by the * {@code createOutputStreamInstance} method. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. */ public ImageOutputStreamSpi(String vendorName, @@ -159,12 +159,12 @@ public abstract class ImageOutputStreamSpi extends IIOServiceProvider { * * @return an {@code ImageOutputStream} instance. * - * @exception IllegalArgumentException if {@code output} is + * @throws IllegalArgumentException if {@code output} is * not an instance of the correct class or is {@code null}. - * @exception IllegalArgumentException if a cache file is needed, + * @throws IllegalArgumentException if a cache file is needed, * but {@code cacheDir} is non-{@code null} and is not a * directory. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see #getOutputClass @@ -186,9 +186,9 @@ public abstract class ImageOutputStreamSpi extends IIOServiceProvider { * * @return an {@code ImageOutputStream} instance. * - * @exception IllegalArgumentException if {@code output} is + * @throws IllegalArgumentException if {@code output} is * not an instance of the correct class or is {@code null}. - * @exception IOException if a cache file is needed but cannot be + * @throws IOException if a cache file is needed but cannot be * created. * * @see #getOutputClass() diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderSpi.java index 4777f989c4b4e156cf0a12ab9448c5961b846679..f20f1bd6eb0a5afc5240fbba922a043896371cad 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderSpi.java @@ -180,15 +180,15 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * {@code getImageMetadataFormat}. An array of length * 0 is normalized to {@code null}. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. - * @exception IllegalArgumentException if {@code names} + * @throws IllegalArgumentException if {@code names} * is {@code null} or has length 0. - * @exception IllegalArgumentException if {@code readerClassName} + * @throws IllegalArgumentException if {@code readerClassName} * is {@code null}. - * @exception IllegalArgumentException if {@code inputTypes} + * @throws IllegalArgumentException if {@code inputTypes} * is {@code null} or has length 0. */ public ImageReaderSpi(String vendorName, @@ -294,9 +294,9 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * @return {@code true} if it is likely that this stream can * be decoded. * - * @exception IllegalArgumentException if {@code source} is + * @throws IllegalArgumentException if {@code source} is * {@code null}. - * @exception IOException if an I/O error occurs while reading the + * @throws IOException if an I/O error occurs while reading the * stream. */ public abstract boolean canDecodeInput(Object source) throws IOException; @@ -312,7 +312,7 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * * @return an {@code ImageReader} instance. * - * @exception IOException if an error occurs during loading, + * @throws IOException if an error occurs during loading, * or initialization of the reader class, or during instantiation * or initialization of the reader object. */ @@ -338,9 +338,9 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * * @return an {@code ImageReader} instance. * - * @exception IOException if the attempt to instantiate + * @throws IOException if the attempt to instantiate * the reader fails. - * @exception IllegalArgumentException if the + * @throws IllegalArgumentException if the * {@code ImageReader}'s constructor throws an * {@code IllegalArgumentException} to indicate that the * extension object is unsuitable. @@ -362,7 +362,7 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * * @return {@code true} if {@code reader} is recognized. * - * @exception IllegalArgumentException if {@code reader} is + * @throws IllegalArgumentException if {@code reader} is * {@code null}. */ public boolean isOwnReader(ImageReader reader) { diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java index 29ed6de0d50dea580db71cedcd86b88bdaa95db0..7abefdd9431a4207fe3267b748d7f0d162ce408b 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java @@ -199,13 +199,13 @@ public abstract class ImageReaderWriterSpi extends IIOServiceProvider { * {@code getImageMetadataFormat}. An array of length * 0 is normalized to {@code null}. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. - * @exception IllegalArgumentException if {@code names} + * @throws IllegalArgumentException if {@code names} * is {@code null} or has length 0. - * @exception IllegalArgumentException if {@code pluginClassName} + * @throws IllegalArgumentException if {@code pluginClassName} * is {@code null}. */ public ImageReaderWriterSpi(String vendorName, @@ -518,7 +518,7 @@ public abstract class ImageReaderWriterSpi extends IIOServiceProvider { * * @return an {@code IIOMetadataFormat} object. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not a supported name. */ public IIOMetadataFormat getStreamMetadataFormat(String formatName) { @@ -542,7 +542,7 @@ public abstract class ImageReaderWriterSpi extends IIOServiceProvider { * * @return an {@code IIOMetadataFormat} object. * - * @exception IllegalArgumentException if {@code formatName} + * @throws IllegalArgumentException if {@code formatName} * is {@code null} or is not a supported name. */ public IIOMetadataFormat getImageMetadataFormat(String formatName) { diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageWriterSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageWriterSpi.java index 604de8d7b22403013498f4349f634d008501cdf7..de2195988b4d3a5a85830d41d0d33513526fc272 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageWriterSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageWriterSpi.java @@ -181,15 +181,15 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * {@code getImageMetadataFormat}. An array of length * 0 is normalized to {@code null}. * - * @exception IllegalArgumentException if {@code vendorName} + * @throws IllegalArgumentException if {@code vendorName} * is {@code null}. - * @exception IllegalArgumentException if {@code version} + * @throws IllegalArgumentException if {@code version} * is {@code null}. - * @exception IllegalArgumentException if {@code names} + * @throws IllegalArgumentException if {@code names} * is {@code null} or has length 0. - * @exception IllegalArgumentException if {@code writerClassName} + * @throws IllegalArgumentException if {@code writerClassName} * is {@code null}. - * @exception IllegalArgumentException if {@code outputTypes} + * @throws IllegalArgumentException if {@code outputTypes} * is {@code null} or has length 0. */ public ImageWriterSpi(String vendorName, @@ -304,7 +304,7 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * @return {@code true} if this writer is likely to be able * to encode images with the given layout. * - * @exception IllegalArgumentException if {@code type} + * @throws IllegalArgumentException if {@code type} * is {@code null}. */ public abstract boolean canEncodeImage(ImageTypeSpecifier type); @@ -325,7 +325,7 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * @return {@code true} if this writer is likely to be able * to encode this image. * - * @exception IllegalArgumentException if {@code im} + * @throws IllegalArgumentException if {@code im} * is {@code null}. */ public boolean canEncodeImage(RenderedImage im) { @@ -343,7 +343,7 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * * @return an {@code ImageWriter} instance. * - * @exception IOException if an error occurs during loading, + * @throws IOException if an error occurs during loading, * or initialization of the writer class, or during instantiation * or initialization of the writer object. */ @@ -369,9 +369,9 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * * @return an {@code ImageWriter} instance. * - * @exception IOException if the attempt to instantiate + * @throws IOException if the attempt to instantiate * the writer fails. - * @exception IllegalArgumentException if the + * @throws IllegalArgumentException if the * {@code ImageWriter}'s constructor throws an * {@code IllegalArgumentException} to indicate that the * extension object is unsuitable. @@ -388,7 +388,7 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { * * @return {@code true} if {@code writer} is recognized * - * @exception IllegalArgumentException if {@code writer} is + * @throws IllegalArgumentException if {@code writer} is * {@code null}. */ public boolean isOwnWriter(ImageWriter writer) { diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java index 4a43ca8133a5b7d14f12d270021441896dca8c21..64f71f734a9574b87ae0cd9da409df21774ea575 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java @@ -104,7 +104,7 @@ public class ServiceRegistry { * @param categories an {@code Iterator} containing * {@code Class} objects to be used to define categories. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code categories} is {@code null}, or if * one of the categories is not an allowed service type. */ @@ -157,7 +157,7 @@ public class ServiceRegistry { * file violates the specified format or if a provider class * cannot be found and instantiated. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code providerClass} is {@code null}, or if it is * not one of the allowed service types. */ @@ -196,7 +196,7 @@ public class ServiceRegistry { * file violates the specified format or if a provider class * cannot be found and instantiated. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code providerClass} is {@code null}, or if it is * not one of the allowed service types. */ @@ -254,11 +254,11 @@ public class ServiceRegistry { * @return true if no provider of the same class was previously * registered in the same category category. * - * @exception IllegalArgumentException if {@code provider} is + * @throws IllegalArgumentException if {@code provider} is * {@code null}. - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. - * @exception ClassCastException if provider does not implement + * @throws ClassCastException if provider does not implement * the {@code Class} defined by {@code category}. */ public boolean registerServiceProvider(T provider, @@ -292,7 +292,7 @@ public class ServiceRegistry { * * @param provider the service provider object to be registered. * - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code provider} is {@code null}. */ public void registerServiceProvider(Object provider) { @@ -323,7 +323,7 @@ public class ServiceRegistry { * @param providers an Iterator containing service provider * objects to be registered. * - * @exception IllegalArgumentException if {@code providers} + * @throws IllegalArgumentException if {@code providers} * is {@code null} or contains a {@code null} entry. */ public void registerServiceProviders(Iterator providers) { @@ -357,11 +357,11 @@ public class ServiceRegistry { * registered in the same category category, * {@code false} otherwise. * - * @exception IllegalArgumentException if {@code provider} is + * @throws IllegalArgumentException if {@code provider} is * {@code null}. - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. - * @exception ClassCastException if provider does not implement + * @throws ClassCastException if provider does not implement * the class defined by {@code category}. */ public boolean deregisterServiceProvider(T provider, @@ -385,7 +385,7 @@ public class ServiceRegistry { * * @param provider the service provider object to be deregistered. * - * @exception IllegalArgumentException if {@code provider} is + * @throws IllegalArgumentException if {@code provider} is * {@code null}. */ public void deregisterServiceProvider(Object provider) { @@ -408,7 +408,7 @@ public class ServiceRegistry { * @return {@code true} if the given provider has been * registered. * - * @exception IllegalArgumentException if {@code provider} is + * @throws IllegalArgumentException if {@code provider} is * {@code null}. */ public boolean contains(Object provider) { @@ -444,7 +444,7 @@ public class ServiceRegistry { * @return an {@code Iterator} containing service provider * objects from the given category, possibly in order. * - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. */ public Iterator getServiceProviders(Class category, @@ -502,7 +502,7 @@ public class ServiceRegistry { * @return an {@code Iterator} containing service provider * objects from the given category, possibly in order. * - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. */ public Iterator getServiceProviders(Class category, @@ -531,7 +531,7 @@ public class ServiceRegistry { * desired {@code Class} type, or {@code null} is none is * present. * - * @exception IllegalArgumentException if {@code providerClass} is + * @throws IllegalArgumentException if {@code providerClass} is * {@code null}. */ public T getServiceProviderByClass(Class providerClass) { @@ -573,9 +573,9 @@ public class ServiceRegistry { * @return {@code true} if a previously unset ordering * was established. * - * @exception IllegalArgumentException if either provider is + * @throws IllegalArgumentException if either provider is * {@code null} or they are the same object. - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. */ public boolean setOrdering(Class category, @@ -619,9 +619,9 @@ public class ServiceRegistry { * @return {@code true} if a previously set ordering was * disestablished. * - * @exception IllegalArgumentException if either provider is + * @throws IllegalArgumentException if either provider is * {@code null} or they are the same object. - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. */ public boolean unsetOrdering(Class category, @@ -650,7 +650,7 @@ public class ServiceRegistry { * * @param category the category to be emptied. * - * @exception IllegalArgumentException if there is no category + * @throws IllegalArgumentException if there is no category * corresponding to {@code category}. */ public void deregisterAll(Class category) { @@ -677,7 +677,7 @@ public class ServiceRegistry { * currently registered service providers. This method should not * be called from application code. * - * @exception Throwable if an error occurs during superclass + * @throws Throwable if an error occurs during superclass * finalization. * * @deprecated Finalization has been deprecated for removal. See diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java index 6bf14838b7fc42d0e4ee853e9ff9f710033ec228..d5c1ff18e5a6844deb734c5f386ea792f2f39a93 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java @@ -83,9 +83,9 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { * cache file should be created, or {@code null} to use the * system directory. * - * @exception IllegalArgumentException if {@code stream} is + * @throws IllegalArgumentException if {@code stream} is * {@code null}. - * @exception IllegalArgumentException if {@code cacheDir} is + * @throws IllegalArgumentException if {@code cacheDir} is * non-{@code null} but is not a directory. * @throws IOException if a cache file cannot be created. */ diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java index 5a2a54abcaa7926120ef34915a11778c9c866500..904515b6f825f0808f38131c0ea0d54db957defa 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java @@ -69,11 +69,11 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { * cache file should be created, or {@code null} to use the * system directory. * - * @exception IllegalArgumentException if {@code stream} + * @throws IllegalArgumentException if {@code stream} * is {@code null}. - * @exception IllegalArgumentException if {@code cacheDir} is + * @throws IllegalArgumentException if {@code cacheDir} is * non-{@code null} but is not a directory. - * @exception IOException if a cache file cannot be created. + * @throws IOException if a cache file cannot be created. */ public FileCacheImageOutputStream(OutputStream stream, File cacheDir) throws IOException { @@ -159,9 +159,9 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { * performed. The file length will not be increased until a write * is performed. * - * @exception IndexOutOfBoundsException if {@code pos} is smaller + * @throws IndexOutOfBoundsException if {@code pos} is smaller * than the flushed position. - * @exception IOException if any other I/O error occurs. + * @throws IOException if any other I/O error occurs. */ public void seek(long pos) throws IOException { checkClosed(); @@ -223,7 +223,7 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { * is closed and removed. The destination {@code OutputStream} * is not closed. * - * @exception IOException if an error occurs. + * @throws IOException if an error occurs. */ public void close() throws IOException { maxStreamPos = cache.length(); diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java index b1cce6fae4cc64bd98db88d535e8cb088b9478f6..ef127ddfa2e94419ffa6afc64334d4818ec29678 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java @@ -60,13 +60,13 @@ public class FileImageInputStream extends ImageInputStreamImpl { * * @param f a {@code File} to read from. * - * @exception IllegalArgumentException if {@code f} is + * @throws IllegalArgumentException if {@code f} is * {@code null}. - * @exception SecurityException if a security manager exists + * @throws SecurityException if a security manager exists * and does not allow read access to the file. - * @exception FileNotFoundException if {@code f} is a + * @throws FileNotFoundException if {@code f} is a * directory or cannot be opened for reading for any other reason. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public FileImageInputStream(File f) throws FileNotFoundException, IOException { @@ -83,7 +83,7 @@ public class FileImageInputStream extends ImageInputStreamImpl { * * @param raf a {@code RandomAccessFile} to read from. * - * @exception IllegalArgumentException if {@code raf} is + * @throws IllegalArgumentException if {@code raf} is * {@code null}. */ public FileImageInputStream(RandomAccessFile raf) { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java index 715b43f40fb764aa4b3df57941cef1959c7029d6..96d84ef652f52327cec673c70a4a0c922ef2b6bf 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java @@ -55,14 +55,14 @@ public class FileImageOutputStream extends ImageOutputStreamImpl { * * @param f a {@code File} to write to. * - * @exception IllegalArgumentException if {@code f} is + * @throws IllegalArgumentException if {@code f} is * {@code null}. - * @exception SecurityException if a security manager exists + * @throws SecurityException if a security manager exists * and does not allow write access to the file. - * @exception FileNotFoundException if {@code f} does not denote + * @throws FileNotFoundException if {@code f} does not denote * a regular file or it cannot be opened for reading and writing for any * other reason. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public FileImageOutputStream(File f) throws FileNotFoundException, IOException { @@ -75,7 +75,7 @@ public class FileImageOutputStream extends ImageOutputStreamImpl { * * @param raf a {@code RandomAccessFile} to write to. * - * @exception IllegalArgumentException if {@code raf} is + * @throws IllegalArgumentException if {@code raf} is * {@code null}. */ public FileImageOutputStream(RandomAccessFile raf) { @@ -141,9 +141,9 @@ public class FileImageOutputStream extends ImageOutputStreamImpl { * performed. The file length will not be increased until a write * is performed. * - * @exception IndexOutOfBoundsException if {@code pos} is smaller + * @throws IndexOutOfBoundsException if {@code pos} is smaller * than the flushed position. - * @exception IOException if any other I/O error occurs. + * @throws IOException if any other I/O error occurs. */ public void seek(long pos) throws IOException { checkClosed(); diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java index d8999d4a884de701c13da49bef0568403cb7c557..11251ac5938ae8dca8cbfc0379d0453170ce8551 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java @@ -100,7 +100,7 @@ public interface ImageInputStream extends DataInput, Closeable { * @return a byte value from the stream, as an int, or -1 to * indicate EOF. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ int read() throws IOException; @@ -118,10 +118,10 @@ public interface ImageInputStream extends DataInput, Closeable { * @return the number of bytes actually read, or {@code -1} * to indicate EOF. * - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ int read(byte[] b) throws IOException; @@ -142,12 +142,12 @@ public interface ImageInputStream extends DataInput, Closeable { * @return the number of bytes actually read, or {@code -1} * to indicate EOF. * - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code b.length}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ int read(byte[] b, int off, int len) throws IOException; @@ -164,12 +164,12 @@ public interface ImageInputStream extends DataInput, Closeable { * @param buf an IIOByteBuffer object to be modified. * @param len the maximum number of {@code byte}s to read. * - * @exception IndexOutOfBoundsException if {@code len} is + * @throws IndexOutOfBoundsException if {@code len} is * negative. - * @exception NullPointerException if {@code buf} is + * @throws NullPointerException if {@code buf} is * {@code null}. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readBytes(IIOByteBuffer buf, int len) throws IOException; @@ -183,8 +183,8 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a boolean value from the stream. * - * @exception java.io.EOFException if the end of the stream is reached. - * @exception IOException if an I/O error occurs. + * @throws java.io.EOFException if the end of the stream is reached. + * @throws IOException if an I/O error occurs. */ boolean readBoolean() throws IOException; @@ -201,8 +201,8 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a signed byte value from the stream. * - * @exception java.io.EOFException if the end of the stream is reached. - * @exception IOException if an I/O error occurs. + * @throws java.io.EOFException if the end of the stream is reached. + * @throws IOException if an I/O error occurs. */ byte readByte() throws IOException; @@ -225,8 +225,8 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return an unsigned byte value from the stream. * - * @exception java.io.EOFException if the end of the stream is reached. - * @exception IOException if an I/O error occurs. + * @throws java.io.EOFException if the end of the stream is reached. + * @throws IOException if an I/O error occurs. */ int readUnsignedByte() throws IOException; @@ -240,9 +240,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a signed short value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -261,9 +261,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return an unsigned short value from the stream, as an int. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -278,9 +278,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return an unsigned char value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #readUnsignedShort */ @@ -296,9 +296,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a signed int value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -316,9 +316,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return an unsigned int value from the stream, as a long. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -334,9 +334,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a signed long value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -352,9 +352,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a float value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -370,9 +370,9 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a double value from the stream. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getByteOrder */ @@ -408,7 +408,7 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a String containing a line of text from the stream. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ String readLine() throws IOException; @@ -488,11 +488,11 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a String read from the stream. * - * @exception java.io.EOFException if this stream reaches the end + * @throws java.io.EOFException if this stream reaches the end * before reading all the bytes. - * @exception java.io.UTFDataFormatException if the bytes do not represent + * @throws java.io.UTFDataFormatException if the bytes do not represent * a valid modified UTF-8 encoding of a string. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ String readUTF() throws IOException; @@ -509,14 +509,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code b} to write to. * @param len the maximum number of {@code byte}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code b.length}. - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(byte[] b, int off, int len) throws IOException; @@ -531,11 +531,11 @@ public interface ImageInputStream extends DataInput, Closeable { * * @param b an array of {@code byte}s. * - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(byte[] b) throws IOException; @@ -553,14 +553,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code s} to write to. * @param len the maximum number of {@code short}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code s.length}. - * @exception NullPointerException if {@code s} is + * @throws NullPointerException if {@code s} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(short[] s, int off, int len) throws IOException; @@ -578,14 +578,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code c} to write to. * @param len the maximum number of {@code char}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code c.length}. - * @exception NullPointerException if {@code c} is + * @throws NullPointerException if {@code c} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(char[] c, int off, int len) throws IOException; @@ -603,14 +603,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code i} to write to. * @param len the maximum number of {@code int}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code i.length}. - * @exception NullPointerException if {@code i} is + * @throws NullPointerException if {@code i} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(int[] i, int off, int len) throws IOException; @@ -628,14 +628,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code l} to write to. * @param len the maximum number of {@code long}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code l.length}. - * @exception NullPointerException if {@code l} is + * @throws NullPointerException if {@code l} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(long[] l, int off, int len) throws IOException; @@ -653,14 +653,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code f} to write to. * @param len the maximum number of {@code float}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code f.length}. - * @exception NullPointerException if {@code f} is + * @throws NullPointerException if {@code f} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(float[] f, int off, int len) throws IOException; @@ -678,14 +678,14 @@ public interface ImageInputStream extends DataInput, Closeable { * @param off the starting position within {@code d} to write to. * @param len the maximum number of {@code double}s to read. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code d.length}. - * @exception NullPointerException if {@code d} is + * @throws NullPointerException if {@code d} is * {@code null}. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void readFully(double[] d, int off, int len) throws IOException; @@ -695,7 +695,7 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return a long containing the position of the stream. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ long getStreamPosition() throws IOException; @@ -714,7 +714,7 @@ public interface ImageInputStream extends DataInput, Closeable { * @return an {@code int} containing the bit offset between * 0 and 7, inclusive. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #setBitOffset */ @@ -731,9 +731,9 @@ public interface ImageInputStream extends DataInput, Closeable { * @param bitOffset the desired offset, as an {@code int} * between 0 and 7, inclusive. * - * @exception IllegalArgumentException if {@code bitOffset} + * @throws IllegalArgumentException if {@code bitOffset} * is not between 0 and 7, inclusive. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #getBitOffset */ @@ -748,9 +748,9 @@ public interface ImageInputStream extends DataInput, Closeable { * @return an {@code int} containing the value {@code 0} * or {@code 1}. * - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bits. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ int readBit() throws IOException; @@ -788,11 +788,11 @@ public interface ImageInputStream extends DataInput, Closeable { * @return the bitstring, as a {@code long} with the last bit * read stored in the least significant bit. * - * @exception IllegalArgumentException if {@code numBits} + * @throws IllegalArgumentException if {@code numBits} * is not between 0 and 64, inclusive. - * @exception java.io.EOFException if the stream reaches the end before + * @throws java.io.EOFException if the stream reaches the end before * reading all the bits. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ long readBits(int numBits) throws IOException; @@ -803,7 +803,7 @@ public interface ImageInputStream extends DataInput, Closeable { * @return a {@code long} containing the length of the * stream, if known, or else {@code -1}. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ long length() throws IOException; @@ -820,7 +820,7 @@ public interface ImageInputStream extends DataInput, Closeable { * * @return an {@code int} representing the number of bytes skipped. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ int skipBytes(int n) throws IOException; @@ -835,7 +835,7 @@ public interface ImageInputStream extends DataInput, Closeable { * @return a {@code long} representing the number of bytes * skipped. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ long skipBytes(long n) throws IOException; @@ -855,9 +855,9 @@ public interface ImageInputStream extends DataInput, Closeable { * @param pos a {@code long} containing the desired file * pointer position. * - * @exception IndexOutOfBoundsException if {@code pos} is smaller + * @throws IndexOutOfBoundsException if {@code pos} is smaller * than the flushed position. - * @exception IOException if any other I/O error occurs. + * @throws IOException if any other I/O error occurs. */ void seek(long pos) throws IOException; @@ -897,7 +897,7 @@ public interface ImageInputStream extends DataInput, Closeable { *

    An {@code IOException} will be thrown if the previous * marked position lies in the discarded portion of the stream. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void reset() throws IOException; @@ -915,10 +915,10 @@ public interface ImageInputStream extends DataInput, Closeable { * @param pos a {@code long} containing the length of the * stream prefix that may be flushed. * - * @exception IndexOutOfBoundsException if {@code pos} lies + * @throws IndexOutOfBoundsException if {@code pos} lies * in the flushed portion of the stream or past the current stream * position. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void flushBefore(long pos) throws IOException; @@ -927,7 +927,7 @@ public interface ImageInputStream extends DataInput, Closeable { * stream position. Equivalent to * {@code flushBefore(getStreamPosition())}. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void flush() throws IOException; @@ -993,7 +993,7 @@ public interface ImageInputStream extends DataInput, Closeable { * this interface to release resources associated with the stream * such as memory, disk space, or file descriptors. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void close() throws IOException; } diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java index 053bbf7491826e852d0b0f466f68edf37841e0f7..f9bb1235660a761ba3e284649d0395bb2e1a62d7 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java @@ -103,7 +103,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * Subclasses may call this method from any of their methods that * require the stream not to be closed. * - * @exception IOException if the stream is closed. + * @throws IOException if the stream is closed. */ protected final void checkClosed() throws IOException { if (isClosed) { @@ -134,7 +134,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @return the value of the next byte in the stream, or {@code -1} * if EOF is reached. * - * @exception IOException if the stream has been closed. + * @throws IOException if the stream has been closed. */ public abstract int read() throws IOException; @@ -147,9 +147,9 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @return the number of bytes actually read, or {@code -1} * to indicate EOF. * - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public int read(byte[] b) throws IOException { return read(b, 0, b.length); @@ -175,12 +175,12 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @return the number of bytes actually read, or {@code -1} * to indicate EOF. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code b.length}. - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public abstract int read(byte[] b, int off, int len) throws IOException; @@ -729,7 +729,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @return an {@code int} representing the number of bytes * skipped. * - * @exception IOException if {@code getStreamPosition} + * @throws IOException if {@code getStreamPosition} * throws an {@code IOException} when computing either * the starting or ending position. */ @@ -750,7 +750,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @return a {@code long} representing the number of bytes * skipped. * - * @exception IOException if {@code getStreamPosition} + * @throws IOException if {@code getStreamPosition} * throws an {@code IOException} when computing either * the starting or ending position. */ @@ -791,7 +791,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { *

    An {@code IOException} will be thrown if the previous * marked position lies in the discarded portion of the stream. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public void reset() throws IOException { if (markByteStack.empty()) { @@ -865,7 +865,7 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * source. This method should not be called from application * code. * - * @exception Throwable if an error occurs during superclass + * @throws Throwable if an error occurs during superclass * finalization. * * @deprecated Finalization has been deprecated for removal. See diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java index 5c261754c913a36ec6e1facc2568f54de7ea43fe..e88fb00e9cf007a82ee64a572410e170adeb6cd1 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java @@ -66,7 +66,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param b an {@code int} whose lower 8 bits are to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void write(int b) throws IOException; @@ -83,9 +83,9 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * * @param b an array of {@code byte}s to be written. * - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void write(byte[] b) throws IOException; @@ -107,12 +107,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code byte}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code b.length}. - * @exception NullPointerException if {@code b} is + * @throws NullPointerException if {@code b} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void write(byte[] b, int off, int len) throws IOException; @@ -129,7 +129,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * * @param v the {@code boolean} to be written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeBoolean(boolean v) throws IOException; @@ -147,7 +147,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v an {@code int} containing the byte value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeByte(int v) throws IOException; @@ -177,7 +177,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v an {@code int} containing the short value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeShort(int v) throws IOException; @@ -187,7 +187,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v an {@code int} containing the char (unsigned * short) value to be written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * * @see #writeShort(int) */ @@ -222,7 +222,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v an {@code int} containing the value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeInt(int v) throws IOException; @@ -263,7 +263,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v a {@code long} containing the value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeLong(long v) throws IOException; @@ -283,7 +283,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v a {@code float} containing the value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeFloat(float v) throws IOException; @@ -304,7 +304,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param v a {@code double} containing the value to be * written. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeDouble(double v) throws IOException; @@ -330,9 +330,9 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param s a {@code String} containing the value to be * written. * - * @exception NullPointerException if {@code s} is + * @throws NullPointerException if {@code s} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeBytes(String s) throws IOException; @@ -358,9 +358,9 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param s a {@code String} containing the value to be * written. * - * @exception NullPointerException if {@code s} is + * @throws NullPointerException if {@code s} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeChars(String s) throws IOException; @@ -427,11 +427,11 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param s a {@code String} containing the value to be * written. * - * @exception NullPointerException if {@code s} is + * @throws NullPointerException if {@code s} is * {@code null}. - * @exception java.io.UTFDataFormatException if the modified UTF-8 + * @throws java.io.UTFDataFormatException if the modified UTF-8 * representation of {@code s} requires more than 65536 bytes. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeUTF(String s) throws IOException; @@ -452,12 +452,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code short}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code s.length}. - * @exception NullPointerException if {@code s} is + * @throws NullPointerException if {@code s} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeShorts(short[] s, int off, int len) throws IOException; @@ -478,12 +478,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code char}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code c.length}. - * @exception NullPointerException if {@code c} is + * @throws NullPointerException if {@code c} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeChars(char[] c, int off, int len) throws IOException; @@ -504,12 +504,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code int}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code i.length}. - * @exception NullPointerException if {@code i} is + * @throws NullPointerException if {@code i} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeInts(int[] i, int off, int len) throws IOException; @@ -530,12 +530,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code long}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code l.length}. - * @exception NullPointerException if {@code l} is + * @throws NullPointerException if {@code l} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeLongs(long[] l, int off, int len) throws IOException; @@ -556,12 +556,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code float}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code f.length}. - * @exception NullPointerException if {@code f} is + * @throws NullPointerException if {@code f} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeFloats(float[] f, int off, int len) throws IOException; @@ -582,12 +582,12 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param off the start offset in the data. * @param len the number of {@code double}s to write. * - * @exception IndexOutOfBoundsException if {@code off} is + * @throws IndexOutOfBoundsException if {@code off} is * negative, {@code len} is negative, or {@code off + len} * is greater than {@code d.length}. - * @exception NullPointerException if {@code d} is + * @throws NullPointerException if {@code d} is * {@code null}. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeDoubles(double[] d, int off, int len) throws IOException; @@ -606,7 +606,7 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param bit an {@code int} whose least significant bit * is to be written to the stream. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeBit(int bit) throws IOException; @@ -637,9 +637,9 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * * @param numBits an {@code int} between 0 and 64, inclusive. * - * @exception IllegalArgumentException if {@code numBits} is + * @throws IllegalArgumentException if {@code numBits} is * not between 0 and 64, inclusive. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void writeBits(long bits, int numBits) throws IOException; @@ -653,10 +653,10 @@ public interface ImageOutputStream extends ImageInputStream, DataOutput { * @param pos a {@code long} containing the length of the * stream prefix that may be flushed to the destination. * - * @exception IndexOutOfBoundsException if {@code pos} lies + * @throws IndexOutOfBoundsException if {@code pos} lies * in the flushed portion of the stream or past the current stream * position. - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ void flushBefore(long pos) throws IOException; } diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStreamImpl.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStreamImpl.java index 29e55a9a74536c6deaf4cff6b8d4b67b017af234..0bee5c7a240933f5ca2be7e77f2d28741822b8d2 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStreamImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStreamImpl.java @@ -484,7 +484,7 @@ public abstract class ImageOutputStreamImpl * beginning of the {@code write(int)} and * {@code write(byte[], int, int)} methods. * - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ protected final void flushBits() throws IOException { checkClosed(); diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java index 2b0fdd98d6017584f5d74df06ffb316742947703..260a0242546d59d43269a7cce3eb1b89e0ee0ddb 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java @@ -141,7 +141,7 @@ class MemoryCache { * not dispose of any blocks containing bytes written. To dispose * blocks, use {@link #disposeBefore disposeBefore()}. * - * @exception IndexOutOfBoundsException if any portion of + * @throws IndexOutOfBoundsException if any portion of * the requested data is not in the cache (including if {@code pos} * is in a block already disposed), or if either {@code pos} or * {@code len} is < 0. @@ -207,8 +207,8 @@ class MemoryCache { * @param len the number of bytes to be written. * @param pos the cache position at which to begin writing. * - * @exception NullPointerException if {@code b} is {@code null}. - * @exception IndexOutOfBoundsException if {@code off}, + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off}, * {@code len}, or {@code pos} are negative, * or if {@code off+len > b.length}. * @throws IOException if there is an I/O error while writing to the cache @@ -254,7 +254,7 @@ class MemoryCache { * will be written. * @param pos the cache position at which to begin writing. * - * @exception IndexOutOfBoundsException if {@code pos} is negative. + * @throws IndexOutOfBoundsException if {@code pos} is negative. * @throws IOException if there is an I/O error while writing to the cache */ public void write(int b, long pos) throws IOException { @@ -309,8 +309,8 @@ class MemoryCache { * at cache position {@code pos}, into the array * {@code b} at offset {@code off}. * - * @exception NullPointerException if b is {@code null} - * @exception IndexOutOfBoundsException if {@code off}, + * @throws NullPointerException if b is {@code null} + * @throws IndexOutOfBoundsException if {@code off}, * {@code len} or {@code pos} are negative or if * {@code off + len > b.length} or if any portion of the * requested data is not in the cache (including if @@ -349,7 +349,7 @@ class MemoryCache { * Free the blocks up to the position {@code pos}. * The byte at {@code pos} remains available. * - * @exception IndexOutOfBoundsException if {@code pos} + * @throws IndexOutOfBoundsException if {@code pos} * is in a block that has already been disposed. */ public void disposeBefore(long pos) { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java index 44b9d8cd5fbf9c0b3ce2130da8ed12b1bb9dd9f8..ecb30ddba5205e7dc50838ea5b69c6ed35823baf 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java @@ -61,7 +61,7 @@ public class MemoryCacheImageInputStream extends ImageInputStreamImpl { * * @param stream an {@code InputStream} to read from. * - * @exception IllegalArgumentException if {@code stream} is + * @throws IllegalArgumentException if {@code stream} is * {@code null}. */ public MemoryCacheImageInputStream(InputStream stream) { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageOutputStream.java index b90b7f33eacd006f2f9b87b00f975560e9587fd6..676e3c829e34dd8dd860e565b1242e427cdcbf49 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageOutputStream.java @@ -51,7 +51,7 @@ public class MemoryCacheImageOutputStream extends ImageOutputStreamImpl { * * @param stream an {@code OutputStream} to write to. * - * @exception IllegalArgumentException if {@code stream} is + * @throws IllegalArgumentException if {@code stream} is * {@code null}. */ public MemoryCacheImageOutputStream(OutputStream stream) { diff --git a/src/java.desktop/share/classes/javax/swing/AbstractButton.java b/src/java.desktop/share/classes/javax/swing/AbstractButton.java index 8a2936cd4990e1dc2965c2f729ccba751195937f..4f79ac8e2b36af75866dd951c0a7a52f66982ba2 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractButton.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractButton.java @@ -876,7 +876,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl *

  • {@code SwingConstants.LEADING} *
  • {@code SwingConstants.TRAILING} (the default) * - * @exception IllegalArgumentException if textPosition + * @throws IllegalArgumentException if textPosition * is not one of the legal values listed above */ @BeanProperty(visualUpdate = true, enumerationValues = { @@ -953,7 +953,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * {@code IllegalArgumentException} that is thrown for an invalid * value * @return the {@code key} argument - * @exception IllegalArgumentException if key is not one of the legal + * @throws IllegalArgumentException if key is not one of the legal * values listed above * @see #setHorizontalTextPosition * @see #setHorizontalAlignment @@ -984,7 +984,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * {@code IllegalArgumentException} that is thrown for an invalid * value * @return the {@code key} argument - * @exception IllegalArgumentException if key is not one of the legal + * @throws IllegalArgumentException if key is not one of the legal * values listed above */ protected int checkVerticalKey(int key, String exception) { @@ -1571,7 +1571,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * * @since 1.4 * @param index Index into the String to underline - * @exception IllegalArgumentException will be thrown if index + * @throws IllegalArgumentException will be thrown if index * is >= length of the text, or < -1 * @see #getDisplayedMnemonicIndex */ @@ -1654,7 +1654,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * @see #getMultiClickThreshhold * @param threshhold the amount of time required between mouse * press events to generate corresponding action events - * @exception IllegalArgumentException if threshhold < 0 + * @throws IllegalArgumentException if threshhold < 0 * @since 1.4 */ public void setMultiClickThreshhold(long threshhold) { @@ -1791,10 +1791,10 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * @param index the position in the container's list at which to * insert the component, where -1 * means append to the end - * @exception IllegalArgumentException if index is invalid - * @exception IllegalArgumentException if adding the container's parent + * @throws IllegalArgumentException if index is invalid + * @throws IllegalArgumentException if adding the container's parent * to itself - * @exception IllegalArgumentException if adding a window to a container + * @throws IllegalArgumentException if adding a window to a container * @since 1.5 */ protected void addImpl(Component comp, Object constraints, int index) { @@ -3064,7 +3064,7 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * * @param i zero-based index of the key bindings * @return a javax.lang.Object which specifies the key binding - * @exception IllegalArgumentException if the index is + * @throws IllegalArgumentException if the index is * out of bounds * @see #getAccessibleKeyBindingCount */ diff --git a/src/java.desktop/share/classes/javax/swing/AbstractListModel.java b/src/java.desktop/share/classes/javax/swing/AbstractListModel.java index 0396c956597fe5c6dc46846fb428a876098ca551..815fbea84070b252dc8534e7d3cae86ef784444b 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractListModel.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractListModel.java @@ -218,7 +218,7 @@ public abstract class AbstractListModel implements ListModel, Serializable * on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/BorderFactory.java b/src/java.desktop/share/classes/javax/swing/BorderFactory.java index 3fcb5620e692b5bb5439e4a2c33057d10e9670f8..2e4b18848a2e65ccac85d54699e704fd56f7f269 100644 --- a/src/java.desktop/share/classes/javax/swing/BorderFactory.java +++ b/src/java.desktop/share/classes/javax/swing/BorderFactory.java @@ -332,7 +332,7 @@ public class BorderFactory * @param type one of EtchedBorder.RAISED, or * EtchedBorder.LOWERED * @return the Border object - * @exception IllegalArgumentException if type is not either + * @throws IllegalArgumentException if type is not either * EtchedBorder.RAISED or * EtchedBorder.LOWERED * @since 1.3 diff --git a/src/java.desktop/share/classes/javax/swing/BoxLayout.java b/src/java.desktop/share/classes/javax/swing/BoxLayout.java index bc84a4fa58279971dfbbe2453ec71a612782f47e..d20a05ce4ef4eb920eb4c7a5dad6f90fd11f8888 100644 --- a/src/java.desktop/share/classes/javax/swing/BoxLayout.java +++ b/src/java.desktop/share/classes/javax/swing/BoxLayout.java @@ -169,7 +169,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * {@code BoxLayout.X_AXIS, BoxLayout.Y_AXIS, * BoxLayout.LINE_AXIS} or {@code BoxLayout.PAGE_AXIS} * - * @exception AWTError if the value of {@code axis} is invalid + * @throws AWTError if the value of {@code axis} is invalid */ @ConstructorProperties({"target", "axis"}) public BoxLayout(Container target, int axis) { @@ -234,7 +234,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the affected container * - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor */ public synchronized void invalidateLayout(Container target) { @@ -280,7 +280,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container that needs to be laid out * @return the dimensions >= 0 && <= Integer.MAX_VALUE - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor * @see Container * @see #minimumLayoutSize @@ -306,7 +306,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container that needs to be laid out * @return the dimensions >= 0 && <= Integer.MAX_VALUE - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor * @see #preferredLayoutSize * @see #maximumLayoutSize @@ -331,7 +331,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container that needs to be laid out * @return the dimensions >= 0 && <= Integer.MAX_VALUE - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor * @see #preferredLayoutSize * @see #minimumLayoutSize @@ -358,7 +358,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container * @return the alignment >= 0.0f && <= 1.0f - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor */ public synchronized float getLayoutAlignmentX(Container target) { @@ -375,7 +375,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container * @return the alignment >= 0.0f && <= 1.0f - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor */ public synchronized float getLayoutAlignmentY(Container target) { @@ -390,7 +390,7 @@ public class BoxLayout implements LayoutManager2, Serializable { * * @param target the container to lay out * - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * BoxLayout constructor */ public void layoutContainer(Container target) { diff --git a/src/java.desktop/share/classes/javax/swing/DefaultBoundedRangeModel.java b/src/java.desktop/share/classes/javax/swing/DefaultBoundedRangeModel.java index 7e254d5c8b329eb9e894c8aef37ecb775ae7023f..e9bd3d96a6a20f631d8a611f99d4db2956e7060a 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultBoundedRangeModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultBoundedRangeModel.java @@ -417,7 +417,7 @@ public class DefaultBoundedRangeModel implements BoundedRangeModel, Serializable * on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/DefaultButtonModel.java b/src/java.desktop/share/classes/javax/swing/DefaultButtonModel.java index 453b1d0ab0ecff3629914b1a020394324daab94e..d391011167ab6e8b68268cdabaa2f6c9c5fa82a6 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultButtonModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultButtonModel.java @@ -488,7 +488,7 @@ public class DefaultButtonModel implements ButtonModel, Serializable { * on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/DefaultListModel.java b/src/java.desktop/share/classes/javax/swing/DefaultListModel.java index 88210b77c9ce589f9ec4037c36f5d99de76b5fda..9d519927b6774c5f36b8439e85aaee959ec58d00 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultListModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultListModel.java @@ -345,7 +345,7 @@ public class DefaultListModel extends AbstractListModel * * @param element the component to insert * @param index where to insert the new component - * @exception ArrayIndexOutOfBoundsException if the index was invalid + * @throws ArrayIndexOutOfBoundsException if the index was invalid * @see #add(int,Object) * @see Vector#insertElementAt(Object,int) */ diff --git a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java index 55b8fbba66cfac1f2bc1ff0c6e2ea4b04876a083..aa69c2d1ab09e28a1367126e3c3bbec599cb5928 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java @@ -284,7 +284,7 @@ public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, * on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * @@ -750,7 +750,7 @@ public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, * Returns a clone of this selection model with the same selection. * listenerLists are not duplicated. * - * @exception CloneNotSupportedException if the selection model does not + * @throws CloneNotSupportedException if the selection model does not * both (a) implement the Cloneable interface and (b) define a * clone method. */ diff --git a/src/java.desktop/share/classes/javax/swing/DefaultSingleSelectionModel.java b/src/java.desktop/share/classes/javax/swing/DefaultSingleSelectionModel.java index c5c2539d41f4cc608df67824e513d701cfdc2afa..122e635fba1a1255dfa72d6391b048caf3340216 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultSingleSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultSingleSelectionModel.java @@ -178,7 +178,7 @@ Serializable { * on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/JApplet.java b/src/java.desktop/share/classes/javax/swing/JApplet.java index a1d51bf0069f10791400c3b1682273c1fdc2e58c..e5ad62322e65d95bb9aa868db29258cf15f2253b 100644 --- a/src/java.desktop/share/classes/javax/swing/JApplet.java +++ b/src/java.desktop/share/classes/javax/swing/JApplet.java @@ -135,7 +135,7 @@ public class JApplet extends Applet implements Accessible, * This constructor sets the component's locale property to the value * returned by JComponent.getDefaultLocale. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @see JComponent#getDefaultLocale @@ -312,10 +312,10 @@ public class JApplet extends Applet implements Accessible, * @param comp the component to be enhanced * @param constraints the constraints to be respected * @param index the index - * @exception IllegalArgumentException if index is invalid - * @exception IllegalArgumentException if adding the container's parent + * @throws IllegalArgumentException if index is invalid + * @throws IllegalArgumentException if adding the container's parent * to itself - * @exception IllegalArgumentException if adding a window to a container + * @throws IllegalArgumentException if adding a window to a container * * @see #setRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer @@ -423,7 +423,7 @@ public class JApplet extends Applet implements Accessible, * Sets the contentPane property. This method is called by the constructor. * @param contentPane the contentPane object for this applet * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see #getContentPane * @see RootPaneContainer#setContentPane @@ -437,7 +437,7 @@ public class JApplet extends Applet implements Accessible, /** * Returns the layeredPane object for this applet. * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null * @see #setLayeredPane * @see RootPaneContainer#getLayeredPane diff --git a/src/java.desktop/share/classes/javax/swing/JColorChooser.java b/src/java.desktop/share/classes/javax/swing/JColorChooser.java index 29bf7009b4ffc7d3e909fdb93ad5f4af1003afb2..945c6f6069704705a0aab5dc582a3d44fee9c1d9 100644 --- a/src/java.desktop/share/classes/javax/swing/JColorChooser.java +++ b/src/java.desktop/share/classes/javax/swing/JColorChooser.java @@ -150,7 +150,7 @@ public class JColorChooser extends JComponent implements Accessible { * @param title the String containing the dialog's title * @param initialColor the initial Color set when the color-chooser is shown * @return the selected color or null if the user opted out - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -173,7 +173,7 @@ public class JColorChooser extends JComponent implements Accessible { * @param colorTransparencySelectionEnabled true if the transparency of * a color can be selected * @return the selected color or null if the user opted out - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -217,7 +217,7 @@ public class JColorChooser extends JComponent implements Accessible { * @param okListener the ActionListener invoked when "OK" is pressed * @param cancelListener the ActionListener invoked when "Cancel" is pressed * @return a new dialog containing the color-chooser pane - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -343,7 +343,7 @@ public class JColorChooser extends JComponent implements Accessible { * @param r an int specifying the amount of Red * @param g an int specifying the amount of Green * @param b an int specifying the amount of Blue - * @exception IllegalArgumentException if r,g,b values are out of range + * @throws IllegalArgumentException if r,g,b values are out of range * @see java.awt.Color */ public void setColor(int r, int g, int b) { @@ -386,7 +386,7 @@ public class JColorChooser extends JComponent implements Accessible { * TransferHandler. * * @param b the value to set the dragEnabled property to - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -464,7 +464,7 @@ public class JColorChooser extends JComponent implements Accessible { * * @param panel a string that specifies the panel to be removed * @return the color panel - * @exception IllegalArgumentException if panel is not in list of + * @throws IllegalArgumentException if panel is not in list of * known chooser panels */ public AbstractColorChooserPanel removeChooserPanel( AbstractColorChooserPanel panel ) { diff --git a/src/java.desktop/share/classes/javax/swing/JComboBox.java b/src/java.desktop/share/classes/javax/swing/JComboBox.java index fdbbdc686575f26e01f8e0cce1c4ab61071bf07b..f035c186896a671b32f8aeacd110b104324d4abb 100644 --- a/src/java.desktop/share/classes/javax/swing/JComboBox.java +++ b/src/java.desktop/share/classes/javax/swing/JComboBox.java @@ -638,7 +638,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { * * @param anIndex an integer specifying the list item to select, * where 0 specifies the first item in the list and -1 indicates no selection - * @exception IllegalArgumentException if anIndex < -1 or + * @throws IllegalArgumentException if anIndex < -1 or * anIndex is greater than or equal to size */ @BeanProperty(bound = false, preferred = true, description @@ -815,7 +815,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { /** * Checks that the dataModel is an instance of * MutableComboBoxModel. If not, it throws an exception. - * @exception RuntimeException if dataModel is not an + * @throws RuntimeException if dataModel is not an * instance of MutableComboBoxModel. */ void checkMutableComboBoxModel() { @@ -2298,7 +2298,7 @@ implements ItemSelectable,ListDataListener,ActionListener, 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/javax/swing/JComponent.java b/src/java.desktop/share/classes/javax/swing/JComponent.java index c572a12ebb465e801d948c43fea0a45cf050efa5..87b8c3175bdcb1432df7dc64f88abc32b8f02f30 100644 --- a/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -2455,7 +2455,7 @@ public abstract class JComponent extends Container implements Serializable, * * @param condition one of the values listed above * @param map the InputMap to use for the given condition - * @exception IllegalArgumentException if condition is + * @throws IllegalArgumentException if condition is * WHEN_IN_FOCUSED_WINDOW and map * is not an instance of ComponentInputMap; or * if condition is not one of the legal values @@ -2554,7 +2554,7 @@ public abstract class JComponent extends Container implements Serializable, * @return the InputMap for the given condition; * if create is false and the InputMap * hasn't been created, returns null - * @exception IllegalArgumentException if condition + * @throws IllegalArgumentException if condition * is not one of the legal values listed above */ final InputMap getInputMap(int condition, boolean create) { @@ -4623,7 +4623,7 @@ public abstract class JComponent extends Container implements Serializable, * @param propertyName the name of the property that was listened on * @param oldValue the old value of the property * @param newValue the new value of the property - * @exception java.beans.PropertyVetoException when the attempt to set the + * @throws java.beans.PropertyVetoException when the attempt to set the * property is vetoed by the component */ protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue) @@ -4799,7 +4799,7 @@ public abstract class JComponent extends Container implements Serializable, * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/JEditorPane.java b/src/java.desktop/share/classes/javax/swing/JEditorPane.java index 6b9189d550d584c851e9e7a1c93127bc92a9e6f1..f347621a687ce75ab75d5068e10e99145cba9a69 100644 --- a/src/java.desktop/share/classes/javax/swing/JEditorPane.java +++ b/src/java.desktop/share/classes/javax/swing/JEditorPane.java @@ -312,7 +312,7 @@ public class JEditorPane extends JTextComponent { * Creates a JEditorPane based on a specified URL for input. * * @param initialPage the URL - * @exception IOException if the URL is null + * @throws IOException if the URL is null * or cannot be accessed */ public JEditorPane(URL initialPage) throws IOException { @@ -325,7 +325,7 @@ public class JEditorPane extends JTextComponent { * a URL specification. * * @param url the URL - * @exception IOException if the URL is null or + * @throws IOException if the URL is null or * cannot be accessed */ public JEditorPane(String url) throws IOException { @@ -340,7 +340,7 @@ public class JEditorPane extends JTextComponent { * * @param type mime type of the given text * @param text the text to initialize with; may be null - * @exception NullPointerException if the type parameter + * @throws NullPointerException if the type parameter * is null */ public JEditorPane(String type, String text) { @@ -462,7 +462,7 @@ public class JEditorPane extends JTextComponent { * thread is done whether the load was successful or not. * * @param page the URL of the page - * @exception IOException for a null or invalid + * @throws IOException for a null or invalid * page specification, or exception from the stream being read * @see #getPage */ @@ -578,7 +578,7 @@ public class JEditorPane extends JTextComponent { * * @param in the stream from which to read * @param desc an object describing the stream - * @exception IOException as thrown by the stream being + * @throws IOException as thrown by the stream being * used to initialize * @see JTextComponent#read * @see #setDocument @@ -925,7 +925,7 @@ public class JEditorPane extends JTextComponent { * Sets the current URL being displayed. * * @param url the URL for display - * @exception IOException for a null or invalid URL + * @throws IOException for a null or invalid URL * specification */ public void setPage(String url) throws IOException { diff --git a/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/src/java.desktop/share/classes/javax/swing/JFileChooser.java index 8d286e05f3bab1f030e805182ae1aa6ba968051a..a44edec35652fda42fa41a754417c8e6fa773293 100644 --- a/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -303,7 +303,7 @@ public class JFileChooser extends JComponent implements Accessible { /** * Constructs a JFileChooser pointing to the user's * default directory. This default depends on the operating system. - * It is typically the "My Documents" folder on Windows, and the + * It is typically the "Documents" folder on Windows, and the * user's home directory on Unix. */ public JFileChooser() { @@ -315,7 +315,7 @@ public class JFileChooser extends JComponent implements Accessible { * Passing in a null * string causes the file chooser to point to the user's default directory. * This default depends on the operating system. It is - * typically the "My Documents" folder on Windows, and the user's + * typically the "Documents" folder on Windows, and the user's * home directory on Unix. * * @param currentDirectoryPath a String giving the path @@ -330,7 +330,7 @@ public class JFileChooser extends JComponent implements Accessible { * as the path. Passing in a null file * causes the file chooser to point to the user's default directory. * This default depends on the operating system. It is - * typically the "My Documents" folder on Windows, and the user's + * typically the "Documents" folder on Windows, and the user's * home directory on Unix. * * @param currentDirectory a File object specifying @@ -446,7 +446,7 @@ public class JFileChooser extends JComponent implements Accessible { * TransferHandler. * * @param b the value to set the dragEnabled property to - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -570,7 +570,7 @@ public class JFileChooser extends JComponent implements Accessible { * Sets the current directory. Passing in null sets the * file chooser to point to the user's default directory. * This default depends on the operating system. It is - * typically the "My Documents" folder on Windows, and the user's + * typically the "Documents" folder on Windows, and the user's * home directory on Unix. * * If the file passed in as currentDirectory is not a @@ -658,7 +658,7 @@ public class JFileChooser extends JComponent implements Accessible { *
  • JFileChooser.ERROR_OPTION if an error occurs or the * dialog is dismissed * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @see #showDialog @@ -683,7 +683,7 @@ public class JFileChooser extends JComponent implements Accessible { *
  • JFileChooser.ERROR_OPTION if an error occurs or the * dialog is dismissed * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @see #showDialog @@ -743,7 +743,7 @@ public class JFileChooser extends JComponent implements Accessible { *
  • JFileChooser.ERROR_OPTION if an error occurs or the * dialog is dismissed * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -800,7 +800,7 @@ public class JFileChooser extends JComponent implements Accessible { * @param parent the parent component of the dialog; * can be null * @return a new JDialog containing this instance - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 @@ -924,7 +924,7 @@ public class JFileChooser extends JComponent implements Accessible { *
  • JFileChooser.CUSTOM_DIALOG * * - * @exception IllegalArgumentException if dialogType is + * @throws IllegalArgumentException if dialogType is * not legal * * @see #getDialogType @@ -1311,7 +1311,7 @@ public class JFileChooser extends JComponent implements Accessible { *
  • JFileChooser.FILES_AND_DIRECTORIES * * - * @exception IllegalArgumentException if mode is an + * @throws IllegalArgumentException if mode is an * illegal file selection mode * * @see #getFileSelectionMode diff --git a/src/java.desktop/share/classes/javax/swing/JFrame.java b/src/java.desktop/share/classes/javax/swing/JFrame.java index 339268fd16547916f1cc56974a350ce3a69ccd42..9b37ae77ab00876b2de41f11834a50b1f194f6e5 100644 --- a/src/java.desktop/share/classes/javax/swing/JFrame.java +++ b/src/java.desktop/share/classes/javax/swing/JFrame.java @@ -169,7 +169,7 @@ public class JFrame extends Frame implements WindowConstants, * This constructor sets the component's locale property to the value * returned by JComponent.getDefaultLocale. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize @@ -193,7 +193,7 @@ public class JFrame extends Frame implements WindowConstants, * to construct the new Frame; * if gc is null, the system * default GraphicsConfiguration is assumed - * @exception IllegalArgumentException if gc is not from + * @throws IllegalArgumentException if gc is not from * a screen device. This exception is always thrown when * GraphicsEnvironment.isHeadless() returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -213,7 +213,7 @@ public class JFrame extends Frame implements WindowConstants, * returned by JComponent.getDefaultLocale. * * @param title the title for the frame - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize @@ -239,7 +239,7 @@ public class JFrame extends Frame implements WindowConstants, * to construct the new JFrame with; * if gc is null, the system * default GraphicsConfiguration is assumed - * @exception IllegalArgumentException if gc is not from + * @throws IllegalArgumentException if gc is not from * a screen device. This exception is always thrown when * GraphicsEnvironment.isHeadless() returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -357,7 +357,7 @@ public class JFrame extends Frame implements WindowConstants, * * @param operation the operation which should be performed when the * user closes the frame - * @exception IllegalArgumentException if defaultCloseOperation value + * @throws IllegalArgumentException if defaultCloseOperation value * isn't one of the above valid values * @see #addWindowListener * @see #getDefaultCloseOperation @@ -540,10 +540,10 @@ public class JFrame extends Frame implements WindowConstants, * @param comp the component to be enhanced * @param constraints the constraints to be respected * @param index the index - * @exception IllegalArgumentException if index is invalid - * @exception IllegalArgumentException if adding the container's parent + * @throws IllegalArgumentException if index is invalid + * @throws IllegalArgumentException if adding the container's parent * to itself - * @exception IllegalArgumentException if adding a window to a container + * @throws IllegalArgumentException if adding a window to a container * * @see #setRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer @@ -668,7 +668,7 @@ public class JFrame extends Frame implements WindowConstants, * * @param contentPane the contentPane object for this frame * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see #getContentPane * @see RootPaneContainer#setContentPane @@ -696,7 +696,7 @@ public class JFrame extends Frame implements WindowConstants, * This method is called by the constructor. * @param layeredPane the layeredPane object for this frame * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null * @see #getLayeredPane * @see RootPaneContainer#setLayeredPane diff --git a/src/java.desktop/share/classes/javax/swing/JInternalFrame.java b/src/java.desktop/share/classes/javax/swing/JInternalFrame.java index 62efd03c0db844aad94f0065eab55a3c4330fba7..9caa5f966e305112392f4e972ff678dce1328a98 100644 --- a/src/java.desktop/share/classes/javax/swing/JInternalFrame.java +++ b/src/java.desktop/share/classes/javax/swing/JInternalFrame.java @@ -497,10 +497,10 @@ public class JInternalFrame extends JComponent implements * @param comp the component to be enhanced * @param constraints the constraints to be respected * @param index the index - * @exception IllegalArgumentException if index is invalid - * @exception IllegalArgumentException if adding the container's parent + * @throws IllegalArgumentException if index is invalid + * @throws IllegalArgumentException if adding the container's parent * to itself - * @exception IllegalArgumentException if adding a window to a container + * @throws IllegalArgumentException if adding a window to a container * * @see #setRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer @@ -628,7 +628,7 @@ public class JInternalFrame extends JComponent implements * * @param c the content pane for this internal frame * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see RootPaneContainer#getContentPane */ @@ -657,7 +657,7 @@ public class JInternalFrame extends JComponent implements * * @param layered the JLayeredPane for this internal frame * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null * @see RootPaneContainer#setLayeredPane */ @@ -794,7 +794,7 @@ public class JInternalFrame extends JComponent implements * * @param b must be true * - * @exception PropertyVetoException when the attempt to set the + * @throws PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see #isClosed() @@ -906,7 +906,7 @@ public class JInternalFrame extends JComponent implements * * @param b a boolean, where true means to iconify this internal frame and * false means to de-iconify it - * @exception PropertyVetoException when the attempt to set the + * @throws PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED @@ -985,7 +985,7 @@ public class JInternalFrame extends JComponent implements * * @param b a boolean, where true maximizes this internal frame and false * restores it - * @exception PropertyVetoException when the attempt to set the + * @throws PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame */ @BeanProperty(description @@ -1047,7 +1047,7 @@ public class JInternalFrame extends JComponent implements * @param selected a boolean, where true means this internal frame * should become selected (currently active) * and false means it should become deselected - * @exception PropertyVetoException when the attempt to set the + * @throws PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see #isShowing diff --git a/src/java.desktop/share/classes/javax/swing/JLabel.java b/src/java.desktop/share/classes/javax/swing/JLabel.java index 8dff4a8fd25b3ba8eacd741730138d189071d537..eed6a157cc1c05333e505f804986ba72650c09d7 100644 --- a/src/java.desktop/share/classes/javax/swing/JLabel.java +++ b/src/java.desktop/share/classes/javax/swing/JLabel.java @@ -551,7 +551,7 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * * @since 1.4 * @param index Index into the String to underline - * @exception IllegalArgumentException will be thrown if index + * @throws IllegalArgumentException will be thrown if index * is >= length of the text, or < -1 */ @BeanProperty(visualUpdate = true, description @@ -595,7 +595,7 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @param message the IllegalArgumentException detail message * @return the key value if {@code key} is a a legal value for the * horizontalAlignment properties - * @exception IllegalArgumentException if key isn't LEFT, CENTER, RIGHT, + * @throws IllegalArgumentException if key isn't LEFT, CENTER, RIGHT, * LEADING or TRAILING. * @see #setHorizontalTextPosition * @see #setHorizontalAlignment @@ -622,7 +622,7 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @param message the IllegalArgumentException detail message * @return the key value if {@code key} is a legal value for the * verticalAlignment or verticalTextPosition properties - * @exception IllegalArgumentException if key isn't TOP, CENTER, or BOTTOM. + * @throws IllegalArgumentException if key isn't TOP, CENTER, or BOTTOM. * @see #setVerticalAlignment * @see #setVerticalTextPosition */ @@ -1637,7 +1637,7 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * * @param i zero-based index of the key bindings * @return a javax.lang.Object which specifies the key binding - * @exception IllegalArgumentException if the index is + * @throws IllegalArgumentException if the index is * out of bounds * @see #getAccessibleKeyBindingCount */ diff --git a/src/java.desktop/share/classes/javax/swing/JLayer.java b/src/java.desktop/share/classes/javax/swing/JLayer.java index 0ade190ce42fb0c8a5896020af33b1229050faf9..c2076299e442620d55fd514fa003e8d66739cd38 100644 --- a/src/java.desktop/share/classes/javax/swing/JLayer.java +++ b/src/java.desktop/share/classes/javax/swing/JLayer.java @@ -316,7 +316,7 @@ public final class JLayer * a {@code JLayer}. * * @param mgr the specified layout manager - * @exception IllegalArgumentException this method is not supported + * @throws IllegalArgumentException this method is not supported */ public void setLayout(LayoutManager mgr) { if (mgr != null) { diff --git a/src/java.desktop/share/classes/javax/swing/JList.java b/src/java.desktop/share/classes/javax/swing/JList.java index ac4a1e3fe3a6ff67d6b3b0047c3cab8734502b77..220f86aca4ee4fe86b85483913febb4be35642fa 100644 --- a/src/java.desktop/share/classes/javax/swing/JList.java +++ b/src/java.desktop/share/classes/javax/swing/JList.java @@ -445,7 +445,7 @@ public class JList extends JComponent implements Scrollable, Accessible * allowing for tooltips to be provided by the cell renderers. * * @param dataModel the model for the list - * @exception IllegalArgumentException if the model is {@code null} + * @throws IllegalArgumentException if the model is {@code null} */ public JList(ListModel dataModel) { @@ -1202,7 +1202,7 @@ public class JList extends JComponent implements Scrollable, Accessible * list's {@code TransferHandler}. * * @param b whether or not to enable automatic drag handling - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -1493,7 +1493,7 @@ public class JList extends JComponent implements Scrollable, Accessible * Position.Bias.Forward or Position.Bias.Backward. * @return the index of the next list element that * starts with the prefix; otherwise {@code -1} - * @exception IllegalArgumentException if prefix is {@code null} + * @throws IllegalArgumentException if prefix is {@code null} * or startIndex is out of bounds * @since 1.4 */ @@ -1695,7 +1695,7 @@ public class JList extends JComponent implements Scrollable, Accessible * * @param model the ListModel that provides the * list of items for display - * @exception IllegalArgumentException if model is + * @throws IllegalArgumentException if model is * null * @see #getModel * @see #clearSelection @@ -1910,7 +1910,7 @@ public class JList extends JComponent implements Scrollable, Accessible * * @param selectionModel the ListSelectionModel that * implements the selections - * @exception IllegalArgumentException if selectionModel + * @throws IllegalArgumentException if selectionModel * is null * @see #getSelectionModel */ diff --git a/src/java.desktop/share/classes/javax/swing/JMenu.java b/src/java.desktop/share/classes/javax/swing/JMenu.java index dbac4812ca821e3470adee0ae7b829e45f69fe72..1565440969aa89cf9c1be9aa97453d9a21987f79 100644 --- a/src/java.desktop/share/classes/javax/swing/JMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JMenu.java @@ -508,7 +508,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * to manage the idiosyncrasies of the various UI implementations. * * @param d the number of milliseconds to delay - * @exception IllegalArgumentException if d + * @throws IllegalArgumentException if d * is less than 0 */ @BeanProperty(bound = false, expert = true, description @@ -674,7 +674,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @param s the text for the menu item to add * @param pos an integer specifying the position at which to add the * new menu item - * @exception IllegalArgumentException when the value of + * @throws IllegalArgumentException when the value of * pos < 0 */ public void insert(String s, int pos) { @@ -693,7 +693,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @param pos an integer specifying the position at which to add the * new JMenuitem * @return the new menu item - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * pos < 0 */ public JMenuItem insert(JMenuItem mi, int pos) { @@ -713,7 +713,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @param pos an integer specifying the position at which to add the * new menu item * @return the new menu item - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * pos < 0 */ public JMenuItem insert(Action a, int pos) { @@ -734,7 +734,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * * @param index an integer specifying the position at which to * insert the menu separator - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * index < 0 */ public void insertSeparator(int index) { @@ -755,7 +755,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @param pos an integer specifying the position * @return the menu item at the specified position; or null * if the item as the specified position is not a menu item - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * {@code pos} < 0 */ public JMenuItem getItem(int pos) { @@ -790,7 +790,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * yet implemented. * * @return true if the menu can be torn off, else false - * @exception Error if invoked -- this method is not yet implemented + * @throws Error if invoked -- this method is not yet implemented */ @BeanProperty(bound = false) public boolean isTearOff() { @@ -812,7 +812,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * Removes the menu item at the specified index from this menu. * * @param pos the position of the item to be removed - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * pos < 0, or if pos * is greater than the number of menu items */ @@ -1024,7 +1024,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * notification on this event type. The event instance * is created lazily. * - * @exception Error if there is a null listener + * @throws Error if there is a null listener * @see EventListenerList */ protected void fireMenuSelected() { @@ -1054,7 +1054,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * notification on this event type. The event instance * is created lazily. * - * @exception Error if there is a null listener + * @throws Error if there is a null listener * @see EventListenerList */ protected void fireMenuDeselected() { @@ -1084,7 +1084,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * notification on this event type. The event instance * is created lazily. * - * @exception Error if there is a null listener + * @throws Error if there is a null listener * @see EventListenerList */ protected void fireMenuCanceled() { @@ -1238,7 +1238,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * * @param o the new component orientation of this menu and * the components contained within it. - * @exception NullPointerException if orientation is null. + * @throws NullPointerException if orientation is null. * @see java.awt.Component#setComponentOrientation * @see java.awt.Component#getComponentOrientation * @since 1.4 @@ -1275,7 +1275,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @param keyStroke the keystroke combination which will invoke * the JMenuItem's actionlisteners * without navigating the menu hierarchy - * @exception Error if invoked -- this method is not defined for JMenu. + * @throws Error if invoked -- this method is not defined for JMenu. * Use setMnemonic instead */ public void setAccelerator(KeyStroke keyStroke) { diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 99eee90347ba2e2b8ad21258e1e2dfb5bc3d13bd..28a547dc2cb9d2abaa39bcc13f3afb2488be65b7 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -435,7 +435,7 @@ public class JOptionPane extends JComponent implements Accessible * the screen. * * @param message the Object to display - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @return user's input @@ -471,7 +471,7 @@ public class JOptionPane extends JComponent implements Accessible * @param parentComponent the parent Component for the * dialog * @param message the Object to display - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @return user's input @@ -523,7 +523,7 @@ public class JOptionPane extends JComponent implements Accessible * QUESTION_MESSAGE, * or PLAIN_MESSAGE * @return user's input - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -566,7 +566,7 @@ public class JOptionPane extends JComponent implements Accessible * field * @return user's input, or null meaning the user * canceled the input - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -609,7 +609,7 @@ public class JOptionPane extends JComponent implements Accessible * or if the parentComponent has no * Frame, a default Frame is used * @param message the Object to display - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -637,7 +637,7 @@ public class JOptionPane extends JComponent implements Accessible * WARNING_MESSAGE, * QUESTION_MESSAGE, * or PLAIN_MESSAGE - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -666,7 +666,7 @@ public class JOptionPane extends JComponent implements Accessible * or PLAIN_MESSAGE * @param icon an icon to display in the dialog that helps the user * identify the kind of message that is being displayed - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -690,7 +690,7 @@ public class JOptionPane extends JComponent implements Accessible * default Frame is used * @param message the Object to display * @return an integer indicating the option selected by the user - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -718,7 +718,7 @@ public class JOptionPane extends JComponent implements Accessible * YES_NO_CANCEL_OPTION, * or OK_CANCEL_OPTION * @return an int indicating the option selected by the user - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -757,7 +757,7 @@ public class JOptionPane extends JComponent implements Accessible * QUESTION_MESSAGE, * or PLAIN_MESSAGE * @return an integer indicating the option selected by the user - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -795,7 +795,7 @@ public class JOptionPane extends JComponent implements Accessible * or PLAIN_MESSAGE * @param icon the icon to display in the dialog * @return an int indicating the option selected by the user - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -856,7 +856,7 @@ public class JOptionPane extends JComponent implements Accessible * @return an integer indicating the option chosen by the user, * or CLOSED_OPTION if the user closed * the dialog - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -919,7 +919,7 @@ public class JOptionPane extends JComponent implements Accessible * no Frame, a default Frame is used * @param title the title string for the dialog * @return a new JDialog containing this instance - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -946,7 +946,7 @@ public class JOptionPane extends JComponent implements Accessible * * @param title the title string for the dialog * @return a new JDialog containing this instance - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -1508,7 +1508,7 @@ public class JOptionPane extends JComponent implements Accessible * frame's title bar * @return a JInternalFrame containing a * JOptionPane - * @exception RuntimeException if parentComponent does + * @throws RuntimeException if parentComponent does * not have a valid parent */ public JInternalFrame createInternalFrame(Component parentComponent, @@ -1600,7 +1600,7 @@ public class JOptionPane extends JComponent implements Accessible * or getRootFrame * if the component is null, * or does not have a valid Frame parent - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see #getRootFrame @@ -1626,7 +1626,7 @@ public class JOptionPane extends JComponent implements Accessible * frame if the component is null, * or does not have a valid * Frame or Dialog parent - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless @@ -1683,7 +1683,7 @@ public class JOptionPane extends JComponent implements Accessible * which a frame is not provided. * * @return the default Frame to use - * @exception HeadlessException if + * @throws HeadlessException if * GraphicsEnvironment.isHeadless returns * true * @see #setRootFrame @@ -2050,7 +2050,7 @@ public class JOptionPane extends JComponent implements Accessible * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, * QUESTION_MESSAGE, or PLAIN_MESSAGE - * @exception RuntimeException if newType is not one of the + * @throws RuntimeException if newType is not one of the * legal values listed above * @see #getMessageType @@ -2096,7 +2096,7 @@ public class JOptionPane extends JComponent implements Accessible * YES_NO_OPTION, * YES_NO_CANCEL_OPTION, * or OK_CANCEL_OPTION - * @exception RuntimeException if newType is not one of + * @throws RuntimeException if newType is not one of * the legal values listed above * * @see #getOptionType diff --git a/src/java.desktop/share/classes/javax/swing/JPasswordField.java b/src/java.desktop/share/classes/javax/swing/JPasswordField.java index 577998cb3367c9abf49eeb9938a77bd0cb435e20..c6450d0605afc08edbd0c942c2f22a0199a00cec 100644 --- a/src/java.desktop/share/classes/javax/swing/JPasswordField.java +++ b/src/java.desktop/share/classes/javax/swing/JPasswordField.java @@ -288,7 +288,7 @@ public class JPasswordField extends JTextField { * @param offs the offset >= 0 * @param len the length >= 0 * @return the text - * @exception BadLocationException if the offset or length are invalid + * @throws BadLocationException if the offset or length are invalid */ @Deprecated public String getText(int offs, int len) throws BadLocationException { diff --git a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java index ef9ad42ef81d1f1978b1b6c7dbf49fd430009e07..a6811fad5eb7a23b46c5b58da726a56b1a96f016 100644 --- a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java @@ -475,7 +475,7 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { * Removes the component at the specified index from this popup menu. * * @param pos the position of the item to be removed - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * pos < 0, or if the value of * pos is greater than the * number of items @@ -573,7 +573,7 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { * @param a the Action object to insert * @param index specifies the position at which to insert the * Action, where 0 is the first - * @exception IllegalArgumentException if index < 0 + * @throws IllegalArgumentException if index < 0 * @see Action */ public void insert(Action a, int index) { @@ -589,7 +589,7 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { * @param component the Component to insert * @param index specifies the position at which * to insert the component, where 0 is the first - * @exception IllegalArgumentException if index < 0 + * @throws IllegalArgumentException if index < 0 */ public void insert(Component component, int index) { if (index < 0) { diff --git a/src/java.desktop/share/classes/javax/swing/JProgressBar.java b/src/java.desktop/share/classes/javax/swing/JProgressBar.java index 90945bb67e3add75f083db2f727cf939589fd695..edba6e4a5da2ae84725a527865f28a3c073e7e24 100644 --- a/src/java.desktop/share/classes/javax/swing/JProgressBar.java +++ b/src/java.desktop/share/classes/javax/swing/JProgressBar.java @@ -394,7 +394,7 @@ public class JProgressBar extends JComponent implements SwingConstants, Accessib * is {@code SwingConstants.HORIZONTAL}. * * @param newOrientation HORIZONTAL or VERTICAL - * @exception IllegalArgumentException if newOrientation + * @throws IllegalArgumentException if newOrientation * is an illegal value * @see #getOrientation */ diff --git a/src/java.desktop/share/classes/javax/swing/JRootPane.java b/src/java.desktop/share/classes/javax/swing/JRootPane.java index dcc6d6bb4efae6915c99cebb001881617a3fb9f8..48e06a917fc59ce01b710f1f182c9c4aef7b3a00 100644 --- a/src/java.desktop/share/classes/javax/swing/JRootPane.java +++ b/src/java.desktop/share/classes/javax/swing/JRootPane.java @@ -578,7 +578,7 @@ public class JRootPane extends JComponent implements Accessible { * replace it with an opaque JComponent. * * @param content the Container to use for component-contents - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null */ public void setContentPane(Container content) { @@ -605,7 +605,7 @@ public class JRootPane extends JComponent implements Accessible { * typically holds a content pane and an optional JMenuBar. * * @param layered the JLayeredPane to use - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null */ public void setLayeredPane(JLayeredPane layered) { @@ -647,7 +647,7 @@ public class JRootPane extends JComponent implements Accessible { * * @param glass the Component to use as the glass pane * for this JRootPane - * @exception NullPointerException if the glass parameter is + * @throws NullPointerException if the glass parameter is * null */ public void setGlassPane(Component glass) { diff --git a/src/java.desktop/share/classes/javax/swing/JScrollBar.java b/src/java.desktop/share/classes/javax/swing/JScrollBar.java index 6bb997a6150321932bd17b41c9a2e6b1f6bcb4ac..ba65f21a95430851e6b7983f8cd87c4495fa4338 100644 --- a/src/java.desktop/share/classes/javax/swing/JScrollBar.java +++ b/src/java.desktop/share/classes/javax/swing/JScrollBar.java @@ -155,7 +155,7 @@ public class JScrollBar extends JComponent implements Adjustable, Accessible * That way, when the user jumps the knob to an adjacent position, * one or two lines of the original contents remain in view. * - * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL + * @throws IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL * * @see #setOrientation * @see #setValue @@ -279,7 +279,7 @@ public class JScrollBar extends JComponent implements Adjustable, Accessible * HORIZONTAL. * * @param orientation an orientation of the {@code JScrollBar} - * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL + * @throws IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL * @see #getOrientation */ @BeanProperty(preferred = true, visualUpdate = true, enumerationValues = { diff --git a/src/java.desktop/share/classes/javax/swing/JScrollPane.java b/src/java.desktop/share/classes/javax/swing/JScrollPane.java index 2c3302178df99dd6d677d949ae8972e6d827839c..3d5385a34d1e411ba3c46ae83dbaffbdf90afd84 100644 --- a/src/java.desktop/share/classes/javax/swing/JScrollPane.java +++ b/src/java.desktop/share/classes/javax/swing/JScrollPane.java @@ -418,7 +418,7 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce * will invoke syncWithScrollPane on it. * * @param layout the specified layout manager - * @exception ClassCastException if layout is not a + * @throws ClassCastException if layout is not a * ScrollPaneLayout * @see java.awt.Container#getLayout * @see java.awt.Container#setLayout @@ -476,7 +476,7 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce * * * @param policy one of the three values listed above - * @exception IllegalArgumentException if policy + * @throws IllegalArgumentException if policy * is not one of the legal values shown above * @see #getVerticalScrollBarPolicy */ @@ -521,7 +521,7 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce * * * @param policy one of the three values listed above - * @exception IllegalArgumentException if policy + * @throws IllegalArgumentException if policy * is not one of the legal values shown above * @see #getHorizontalScrollBarPolicy */ @@ -1195,7 +1195,7 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce *
  • upperLeft *
  • upperRight * - * @exception IllegalArgumentException if corner key is invalid + * @throws IllegalArgumentException if corner key is invalid */ public void setCorner(String key, Component corner) { diff --git a/src/java.desktop/share/classes/javax/swing/JSeparator.java b/src/java.desktop/share/classes/javax/swing/JSeparator.java index 69d17382acd7b0bf490b0637608cc44292a79793..10a724a7e2ec430dd8ca6cd17f9636a6e7314b40 100644 --- a/src/java.desktop/share/classes/javax/swing/JSeparator.java +++ b/src/java.desktop/share/classes/javax/swing/JSeparator.java @@ -97,7 +97,7 @@ public class JSeparator extends JComponent implements SwingConstants, Accessible * @param orientation an integer specifying * SwingConstants.HORIZONTAL or * SwingConstants.VERTICAL - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is neither SwingConstants.HORIZONTAL nor * SwingConstants.VERTICAL */ @@ -190,7 +190,7 @@ public class JSeparator extends JComponent implements SwingConstants, Accessible * The default value of this property is HORIZONTAL. * @param orientation either SwingConstants.HORIZONTAL * or SwingConstants.VERTICAL - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is neither SwingConstants.HORIZONTAL * nor SwingConstants.VERTICAL * diff --git a/src/java.desktop/share/classes/javax/swing/JSlider.java b/src/java.desktop/share/classes/javax/swing/JSlider.java index 0d826fe7e49e1f910d4a6c1a623a62c06b1df8c9..4682acb8a54dfd4b7e2a63ea81219c0aafa8eec8 100644 --- a/src/java.desktop/share/classes/javax/swing/JSlider.java +++ b/src/java.desktop/share/classes/javax/swing/JSlider.java @@ -920,7 +920,7 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { * @return a new {@code Hashtable} of labels * @see #setLabelTable * @see #setPaintLabels - * @exception IllegalArgumentException if {@code start} is + * @throws IllegalArgumentException if {@code start} is * out of range, or if {@code increment} is less than or equal * to zero */ diff --git a/src/java.desktop/share/classes/javax/swing/JSpinner.java b/src/java.desktop/share/classes/javax/swing/JSpinner.java index a371c557439019959b7a5113bd7755619d0a0049..245212131f2ec2ee960fa0ca3b607400f0b7815a 100644 --- a/src/java.desktop/share/classes/javax/swing/JSpinner.java +++ b/src/java.desktop/share/classes/javax/swing/JSpinner.java @@ -1015,7 +1015,7 @@ public class JSpinner extends JComponent implements Accessible * on the new JFormattedTextField. * * @param spinner the spinner whose model this editor will monitor - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerDateModel * * @see #getModel @@ -1039,7 +1039,7 @@ public class JSpinner extends JComponent implements Accessible * @param dateFormatPattern the initial pattern for the * SimpleDateFormat object that's used to display * and parse the value of the text field. - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerDateModel * * @see #getModel @@ -1064,7 +1064,7 @@ public class JSpinner extends JComponent implements Accessible * will monitor * @param format DateFormat object that's used to display * and parse the value of the text field. - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerDateModel * * @see #getModel @@ -1202,7 +1202,7 @@ public class JSpinner extends JComponent implements Accessible * on the new JFormattedTextField. * * @param spinner the spinner whose model this editor will monitor - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerNumberModel * * @see #getModel @@ -1225,7 +1225,7 @@ public class JSpinner extends JComponent implements Accessible * @param decimalFormatPattern the initial pattern for the * DecimalFormat object that's used to display * and parse the value of the text field. - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerNumberModel or if * decimalFormatPattern is not a legal * argument to DecimalFormat @@ -1251,7 +1251,7 @@ public class JSpinner extends JComponent implements Accessible * @param format the initial pattern for the * DecimalFormat object that's used to display * and parse the value of the text field. - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerNumberModel * * @see #getTextField @@ -1346,7 +1346,7 @@ public class JSpinner extends JComponent implements Accessible * on the new JFormattedTextField. * * @param spinner the spinner whose model this editor will monitor - * @exception IllegalArgumentException if the spinners model is not + * @throws IllegalArgumentException if the spinners model is not * an instance of SpinnerListModel * * @see #getModel diff --git a/src/java.desktop/share/classes/javax/swing/JSplitPane.java b/src/java.desktop/share/classes/javax/swing/JSplitPane.java index bd5e85ed4a6436d87c7e6c3fbd5df641746c4118..5a3cfef943e9ecd8908bbf86abe60a0c8ae1309a 100644 --- a/src/java.desktop/share/classes/javax/swing/JSplitPane.java +++ b/src/java.desktop/share/classes/javax/swing/JSplitPane.java @@ -262,7 +262,7 @@ public class JSplitPane extends JComponent implements Accessible * * @param newOrientation JSplitPane.HORIZONTAL_SPLIT or * JSplitPane.VERTICAL_SPLIT - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT. */ @ConstructorProperties({"orientation"}) @@ -281,7 +281,7 @@ public class JSplitPane extends JComponent implements Accessible * @param newContinuousLayout a boolean, true for the components to * redraw continuously as the divider changes position, false * to wait until the divider position stops changing to redraw - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT */ public JSplitPane(int newOrientation, @@ -304,7 +304,7 @@ public class JSplitPane extends JComponent implements Accessible * appear on the right * of a horizontally-split pane, or at the bottom of a * vertically-split pane - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT */ public JSplitPane(int newOrientation, @@ -334,7 +334,7 @@ public class JSplitPane extends JComponent implements Accessible * appear on the right * of a horizontally-split pane, or at the bottom of a * vertically-split pane - * @exception IllegalArgumentException if orientation + * @throws IllegalArgumentException if orientation * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT */ public JSplitPane(int newOrientation, @@ -622,7 +622,7 @@ public class JSplitPane extends JComponent implements Accessible * * * @param orientation an integer specifying the orientation - * @exception IllegalArgumentException if orientation is not one of: + * @throws IllegalArgumentException if orientation is not one of: * HORIZONTAL_SPLIT or VERTICAL_SPLIT. */ @BeanProperty(enumerationValues = { @@ -701,7 +701,7 @@ public class JSplitPane extends JComponent implements Accessible * extra space. * * @param value as described above - * @exception IllegalArgumentException if value is < 0 or > 1 + * @throws IllegalArgumentException if value is < 0 or > 1 * @since 1.3 */ @BeanProperty(description @@ -754,7 +754,7 @@ public class JSplitPane extends JComponent implements Accessible * @param proportionalLocation a double-precision floating point value * that specifies a percentage, from zero (top/left) to 1.0 * (bottom/right) - * @exception IllegalArgumentException if the specified location is < 0 + * @throws IllegalArgumentException if the specified location is < 0 * or > 1.0 */ @BeanProperty(description @@ -964,7 +964,7 @@ public class JSplitPane extends JComponent implements Accessible * (position) for this component * @param index an integer specifying the index in the container's * list. - * @exception IllegalArgumentException if the constraints + * @throws IllegalArgumentException if the constraints * object does not match an existing component * @see java.awt.Container#addImpl(Component, Object, int) */ diff --git a/src/java.desktop/share/classes/javax/swing/JTabbedPane.java b/src/java.desktop/share/classes/javax/swing/JTabbedPane.java index 4acf4f8a930d4d8e4615a2d3bc88a663ecd9b1fa..2bdd93a7e8db08dc51082f939a85a56b7df23fde 100644 --- a/src/java.desktop/share/classes/javax/swing/JTabbedPane.java +++ b/src/java.desktop/share/classes/javax/swing/JTabbedPane.java @@ -215,7 +215,7 @@ public class JTabbedPane extends JComponent * * @param tabPlacement the placement for the tabs relative to the content * @param tabLayoutPolicy the policy for laying out tabs when all tabs will not fit on one run - * @exception IllegalArgumentException if tab placement or tab layout policy are not + * @throws IllegalArgumentException if tab placement or tab layout policy are not * one of the above supported values * @see #addTab * @since 1.4 @@ -505,7 +505,7 @@ public class JTabbedPane extends JComponent * The default value, if not set, is SwingConstants.TOP. * * @param tabPlacement the placement for the tabs relative to the content - * @exception IllegalArgumentException if tab placement value isn't one + * @throws IllegalArgumentException if tab placement value isn't one * of the above valid values */ @BeanProperty(preferred = true, visualUpdate = true, enumerationValues = { @@ -561,7 +561,7 @@ public class JTabbedPane extends JComponent * ignored. * * @param tabLayoutPolicy the policy used to layout the tabs - * @exception IllegalArgumentException if layoutPolicy value isn't one + * @throws IllegalArgumentException if layoutPolicy value isn't one * of the above valid values * @see #getTabLayoutPolicy * @since 1.4 @@ -609,7 +609,7 @@ public class JTabbedPane extends JComponent * the results will be implementation defined. * * @param index the index to be selected - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < -1 || index >= tab count)} * * @see #getSelectedIndex @@ -696,7 +696,7 @@ public class JTabbedPane extends JComponent * corresponding to the specified component. * * @param c the selected {@code Component} for this {@code TabbedPane} - * @exception IllegalArgumentException if component not found in tabbed + * @throws IllegalArgumentException if component not found in tabbed * pane * @see #getSelectedComponent */ @@ -963,7 +963,7 @@ public class JTabbedPane extends JComponent * its visibility is reset to true to ensure it will be visible * if added to other containers. * @param index the index of the tab to be removed - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #addTab @@ -1084,7 +1084,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the component to remove from the * tabbedpane - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * @see #addTab * @see #removeTabAt @@ -1148,7 +1148,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return the title at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * @see #setTitleAt */ @@ -1161,7 +1161,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return the icon at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setIconAt @@ -1180,7 +1180,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return the icon at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setDisabledIconAt @@ -1198,7 +1198,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return a string containing the tool tip text at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setToolTipTextAt @@ -1214,7 +1214,7 @@ public class JTabbedPane extends JComponent * @param index the index of the item being queried * @return the Color of the tab background at * index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setBackgroundAt @@ -1229,7 +1229,7 @@ public class JTabbedPane extends JComponent * @param index the index of the item being queried * @return the Color of the tab foreground at * index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setForegroundAt @@ -1245,7 +1245,7 @@ public class JTabbedPane extends JComponent * @param index the index of the item being queried * @return true if the tab at index is enabled; * false otherwise - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setEnabledAt @@ -1259,7 +1259,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return the Component at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setComponentAt @@ -1278,7 +1278,7 @@ public class JTabbedPane extends JComponent * @param tabIndex the index of the tab that the mnemonic refers to * @return the key code which represents the mnemonic; * -1 if a mnemonic is not specified for the tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * (tabIndex < 0 || * tabIndex >= tab count) * @see #setDisplayedMnemonicIndexAt(int,int) @@ -1299,7 +1299,7 @@ public class JTabbedPane extends JComponent * @param tabIndex the index of the tab that the mnemonic refers to * @return index representing mnemonic character if one exists; * otherwise returns -1 - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * (tabIndex < 0 || * tabIndex >= tab count) * @see #setDisplayedMnemonicIndexAt(int,int) @@ -1324,7 +1324,7 @@ public class JTabbedPane extends JComponent * index, or null if tab at * index is not currently visible in the UI, * or if there is no UI set on this tabbedpane - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} */ public Rectangle getBoundsAt(int index) { @@ -1346,7 +1346,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the title should be set * @param title the title to be displayed in the tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getTitleAt @@ -1386,7 +1386,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the icon should be set * @param icon the icon to be displayed in the tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setDisabledIconAt @@ -1428,7 +1428,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the disabled icon should be set * @param disabledIcon the icon to be displayed in the tab when disabled - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getDisabledIconAt @@ -1451,7 +1451,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the tooltip text should be set * @param toolTipText the tooltip text to be displayed for the tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getToolTipTextAt @@ -1486,7 +1486,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the background should be set * @param background the color to be displayed in the tab's background - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getBackgroundAt @@ -1517,7 +1517,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where the foreground should be set * @param foreground the color to be displayed as the tab's foreground - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getForegroundAt @@ -1542,7 +1542,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index which should be enabled/disabled * @param enabled whether or not the tab should be enabled - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #isEnabledAt @@ -1562,7 +1562,7 @@ public class JTabbedPane extends JComponent * * @param index the tab index where this component is being placed * @param component the component for the tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #getComponentAt @@ -1638,10 +1638,10 @@ public class JTabbedPane extends JComponent * @since 1.4 * @param tabIndex the index of the tab that the mnemonic refers to * @param mnemonicIndex index into the String to underline - * @exception IndexOutOfBoundsException if tabIndex is + * @throws IndexOutOfBoundsException if tabIndex is * out of range ({@code tabIndex < 0 || tabIndex >= tab * count}) - * @exception IllegalArgumentException will be thrown if + * @throws IllegalArgumentException will be thrown if * mnemonicIndex is >= length of the tab * title , or < -1 * @see #setMnemonicAt(int,int) @@ -1678,7 +1678,7 @@ public class JTabbedPane extends JComponent * @since 1.4 * @param tabIndex the index of the tab that the mnemonic refers to * @param mnemonic the key code which represents the mnemonic - * @exception IndexOutOfBoundsException if tabIndex is out + * @throws IndexOutOfBoundsException if tabIndex is out * of range ({@code tabIndex < 0 || tabIndex >= tab count}) * @see #getMnemonicAt(int) * @see #setDisplayedMnemonicIndexAt(int,int) @@ -2001,7 +2001,7 @@ public class JTabbedPane extends JComponent * * @param i zero-based index of child * @return the Accessible child of the object - * @exception IllegalArgumentException if index is out of bounds + * @throws IllegalArgumentException if index is out of bounds */ public Accessible getAccessibleChild(int i) { if (i < 0 || i >= getTabCount()) { @@ -2426,9 +2426,9 @@ public class JTabbedPane extends JComponent * @param index the tab index where the component should be set * @param component the component to render the title for the * specified tab - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} - * @exception IllegalArgumentException if component has already been + * @throws IllegalArgumentException if component has already been * added to this JTabbedPane * * @see #getTabComponentAt @@ -2456,7 +2456,7 @@ public class JTabbedPane extends JComponent * * @param index the index of the item being queried * @return the tab component at index - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * {@code (index < 0 || index >= tab count)} * * @see #setTabComponentAt diff --git a/src/java.desktop/share/classes/javax/swing/JTable.java b/src/java.desktop/share/classes/javax/swing/JTable.java index 9af6a1ba616415e08121bf8c8b418a1960cabc8e..5d27be294541dcf88d0cf3176c229678956062a6 100644 --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java @@ -991,7 +991,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * the row margin. * * @param rowHeight new row height - * @exception IllegalArgumentException if rowHeight is + * @throws IllegalArgumentException if rowHeight is * less than 1 * @see #getRowHeight */ @@ -1037,7 +1037,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @param row the row whose height is being changed * @param rowHeight new row height, in pixels - * @exception IllegalArgumentException if rowHeight is + * @throws IllegalArgumentException if rowHeight is * less than 1 * @since 1.3 */ @@ -1126,7 +1126,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * The default color is look and feel dependent. * * @param gridColor the new color of the grid lines - * @exception IllegalArgumentException if gridColor is null + * @throws IllegalArgumentException if gridColor is null * @see #getGridColor */ @BeanProperty(description @@ -1485,7 +1485,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * table's {@code TransferHandler}. * * @param b whether or not to enable automatic drag handling - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -2220,7 +2220,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * Selects the rows from index0 to index1, * inclusive. * - * @exception IllegalArgumentException if index0 or + * @throws IllegalArgumentException if index0 or * index1 lie outside * [0, getRowCount()-1] * @param index0 one end of the interval @@ -2234,7 +2234,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * Selects the columns from index0 to index1, * inclusive. * - * @exception IllegalArgumentException if index0 or + * @throws IllegalArgumentException if index0 or * index1 lie outside * [0, getColumnCount()-1] * @param index0 one end of the interval @@ -2248,7 +2248,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * Adds the rows from index0 to index1, inclusive, to * the current selection. * - * @exception IllegalArgumentException if index0 or index1 + * @throws IllegalArgumentException if index0 or index1 * lie outside [0, getRowCount()-1] * @param index0 one end of the interval * @param index1 the other end of the interval @@ -2261,7 +2261,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * Adds the columns from index0 to index1, * inclusive, to the current selection. * - * @exception IllegalArgumentException if index0 or + * @throws IllegalArgumentException if index0 or * index1 lie outside * [0, getColumnCount()-1] * @param index0 one end of the interval @@ -2274,7 +2274,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable /** * Deselects the rows from index0 to index1, inclusive. * - * @exception IllegalArgumentException if index0 or + * @throws IllegalArgumentException if index0 or * index1 lie outside * [0, getRowCount()-1] * @param index0 one end of the interval @@ -2287,7 +2287,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable /** * Deselects the columns from index0 to index1, inclusive. * - * @exception IllegalArgumentException if index0 or + * @throws IllegalArgumentException if index0 or * index1 lie outside * [0, getColumnCount()-1] * @param index0 one end of the interval @@ -2596,7 +2596,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * equals. * * @return the TableColumn object that matches the identifier - * @exception IllegalArgumentException if identifier is null or no TableColumn has this identifier + * @throws IllegalArgumentException if identifier is null or no TableColumn has this identifier * * @param identifier the identifier object */ @@ -5481,6 +5481,21 @@ public class JTable extends JComponent implements TableModelListener, Scrollable return this; } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleBooleanRenderer(); + } + return accessibleContext; + } + + class AccessibleBooleanRenderer extends JCheckBox.AccessibleJCheckBox { + @Override + public AccessibleAction getAccessibleAction() { + return null; + } + } } /** @@ -8340,7 +8355,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * * @return this component's locale; if this component does * not have a locale, the locale of its parent is returned - * @exception IllegalComponentStateException if the + * @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 @@ -8396,7 +8411,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @return the AccessibleAction, or null */ public AccessibleAction getAccessibleAction() { - return getCurrentAccessibleContext().getAccessibleAction(); + AccessibleContext ac = getCurrentAccessibleContext(); + if (ac != null) { + return ac.getAccessibleAction(); + } + return null; } /** @@ -9142,7 +9161,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * * @return this component's locale; if this component does * not have a locale, the locale of its parent is returned - * @exception IllegalComponentStateException if the + * @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 diff --git a/src/java.desktop/share/classes/javax/swing/JTextArea.java b/src/java.desktop/share/classes/javax/swing/JTextArea.java index ecc9342f05a0dd4c9bca710f4a09449312cb18c2..03b3bc7e9bd20979b5e8dffd1379718f2a1fb21b 100644 --- a/src/java.desktop/share/classes/javax/swing/JTextArea.java +++ b/src/java.desktop/share/classes/javax/swing/JTextArea.java @@ -166,7 +166,7 @@ public class JTextArea extends JTextComponent { * * @param rows the number of rows >= 0 * @param columns the number of columns >= 0 - * @exception IllegalArgumentException if the rows or columns + * @throws IllegalArgumentException if the rows or columns * arguments are negative. */ public JTextArea(int rows, int columns) { @@ -180,7 +180,7 @@ public class JTextArea extends JTextComponent { * @param text the text to be displayed, or null * @param rows the number of rows >= 0 * @param columns the number of columns >= 0 - * @exception IllegalArgumentException if the rows or columns + * @throws IllegalArgumentException if the rows or columns * arguments are negative. */ public JTextArea(String text, int rows, int columns) { @@ -206,7 +206,7 @@ public class JTextArea extends JTextComponent { * @param text the text to be displayed, null if none * @param rows the number of rows >= 0 * @param columns the number of columns >= 0 - * @exception IllegalArgumentException if the rows or columns + * @throws IllegalArgumentException if the rows or columns * arguments are negative. */ public JTextArea(Document doc, String text, int rows, int columns) { @@ -370,7 +370,7 @@ public class JTextArea extends JTextComponent { * * @param offset the offset >= 0 * @return the line number >= 0 - * @exception BadLocationException thrown if the offset is + * @throws BadLocationException thrown if the offset is * less than zero or greater than the document length. */ public int getLineOfOffset(int offset) throws BadLocationException { @@ -401,7 +401,7 @@ public class JTextArea extends JTextComponent { * * @param line the line number to translate >= 0 * @return the offset >= 0 - * @exception BadLocationException thrown if the line is + * @throws BadLocationException thrown if the line is * less than zero or greater or equal to the number of * lines contained in the document (as reported by * getLineCount). @@ -424,7 +424,7 @@ public class JTextArea extends JTextComponent { * * @param line the line >= 0 * @return the offset >= 0 - * @exception BadLocationException Thrown if the line is + * @throws BadLocationException Thrown if the line is * less than zero or greater or equal to the number of * lines contained in the document (as reported by * getLineCount). @@ -452,7 +452,7 @@ public class JTextArea extends JTextComponent { * * @param str the text to insert * @param pos the position at which to insert >= 0 - * @exception IllegalArgumentException if pos is an + * @throws IllegalArgumentException if pos is an * invalid position in the model * @see TextComponent#setText * @see #replaceRange @@ -493,7 +493,7 @@ public class JTextArea extends JTextComponent { * @param str the text to use as the replacement * @param start the start position >= 0 * @param end the end position >= start - * @exception IllegalArgumentException if part of the range is an + * @throws IllegalArgumentException if part of the range is an * invalid position in the model * @see #insert */ @@ -532,7 +532,7 @@ public class JTextArea extends JTextComponent { * setting the new value. * * @param rows the number of rows >= 0 - * @exception IllegalArgumentException if rows is less than 0 + * @throws IllegalArgumentException if rows is less than 0 * @see #getRows */ @BeanProperty(bound = false, description @@ -576,7 +576,7 @@ public class JTextArea extends JTextComponent { * after setting the new value. * * @param columns the number of columns >= 0 - * @exception IllegalArgumentException if columns is less than 0 + * @throws IllegalArgumentException if columns is less than 0 * @see #getColumns */ @BeanProperty(bound = false, description @@ -726,7 +726,7 @@ public class JTextArea extends JTextComponent { * @param direction Less than zero to scroll up/left, * greater than zero for down/right. * @return The "unit" increment for scrolling in the specified direction - * @exception IllegalArgumentException for an invalid orientation + * @throws IllegalArgumentException for an invalid orientation * @see JScrollBar#setUnitIncrement * @see #getRowHeight * @see #getColumnWidth diff --git a/src/java.desktop/share/classes/javax/swing/JTextField.java b/src/java.desktop/share/classes/javax/swing/JTextField.java index 3abe09d056542f18aebb4b8dc2c5d62779d77721..0d66209d8af5bc075f43b00addc84061378817c3 100644 --- a/src/java.desktop/share/classes/javax/swing/JTextField.java +++ b/src/java.desktop/share/classes/javax/swing/JTextField.java @@ -242,7 +242,7 @@ public class JTextField extends JTextComponent implements SwingConstants { * the preferred width >= 0; if columns * is set to zero, the preferred width will be whatever * naturally results from the component implementation - * @exception IllegalArgumentException if columns < 0 + * @throws IllegalArgumentException if columns < 0 */ public JTextField(Document doc, String text, int columns) { if (columns < 0) { @@ -343,7 +343,7 @@ public class JTextField extends JTextComponent implements SwingConstants { * and a PropertyChange event ("horizontalAlignment") is fired. * * @param alignment the alignment - * @exception IllegalArgumentException if alignment + * @throws IllegalArgumentException if alignment * is not a valid key */ @BeanProperty(preferred = true, enumerationValues = { @@ -393,7 +393,7 @@ public class JTextField extends JTextComponent implements SwingConstants { * and then invalidate the layout. * * @param columns the number of columns >= 0 - * @exception IllegalArgumentException if columns + * @throws IllegalArgumentException if columns * is less than 0 */ @BeanProperty(bound = false, description diff --git a/src/java.desktop/share/classes/javax/swing/JTextPane.java b/src/java.desktop/share/classes/javax/swing/JTextPane.java index 41e16034c23fb0a56b311b6902ddaf96c8abddb9..228181f31f76a5c31c204860d652d92ef2cea19c 100644 --- a/src/java.desktop/share/classes/javax/swing/JTextPane.java +++ b/src/java.desktop/share/classes/javax/swing/JTextPane.java @@ -138,7 +138,7 @@ public class JTextPane extends JEditorPane { * must be a StyledDocument. * * @param doc the document to display/edit - * @exception IllegalArgumentException if doc can't + * @throws IllegalArgumentException if doc can't * be narrowed to a StyledDocument which is the * required type of model for this text component */ @@ -480,7 +480,7 @@ public class JTextPane extends JEditorPane { * establishes the content type of the editor. * * @param kit the desired editor behavior - * @exception IllegalArgumentException if kit is not a + * @throws IllegalArgumentException if kit is not a * StyledEditorKit */ public final void setEditorKit(EditorKit kit) { diff --git a/src/java.desktop/share/classes/javax/swing/JToolBar.java b/src/java.desktop/share/classes/javax/swing/JToolBar.java index 114ef0d169c2a8c0c97c01f858c237f3fbd9a119..4d93a1bceefe453f48a4aa746d74bf65b9725ec2 100644 --- a/src/java.desktop/share/classes/javax/swing/JToolBar.java +++ b/src/java.desktop/share/classes/javax/swing/JToolBar.java @@ -142,7 +142,7 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible * @param name the name of the tool bar * @param orientation the initial orientation -- it must be * either HORIZONTAL or VERTICAL - * @exception IllegalArgumentException if orientation is neither + * @throws IllegalArgumentException if orientation is neither * HORIZONTAL nor VERTICAL * @since 1.3 */ @@ -406,7 +406,7 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible * * @param o the new orientation -- either HORIZONTAL or * VERTICAL - * @exception IllegalArgumentException if orientation is neither + * @throws IllegalArgumentException if orientation is neither * HORIZONTAL nor VERTICAL * @see #getOrientation */ diff --git a/src/java.desktop/share/classes/javax/swing/JTree.java b/src/java.desktop/share/classes/javax/swing/JTree.java index ae90ea8be8bec502faf56b15683af34a8d75a161..e6e591bad27ca8843dbf796fb40d7f2dca988068 100644 --- a/src/java.desktop/share/classes/javax/swing/JTree.java +++ b/src/java.desktop/share/classes/javax/swing/JTree.java @@ -1251,7 +1251,7 @@ public class JTree extends JComponent implements Scrollable, Accessible * tree's {@code TransferHandler}. * * @param b whether or not to enable automatic drag handling - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -3087,7 +3087,7 @@ public class JTree extends JComponent implements Scrollable, Accessible * Position.Bias.Forward or Position.Bias.Backward. * @return the TreePath of the next tree element that * starts with the prefix; otherwise null - * @exception IllegalArgumentException if prefix is null + * @throws IllegalArgumentException if prefix is null * or startingRow is out of bounds * @since 1.4 */ @@ -5053,7 +5053,7 @@ public class JTree extends JComponent implements Scrollable, 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/javax/swing/JViewport.java b/src/java.desktop/share/classes/javax/swing/JViewport.java index e3974a84f27761730a95371f7e6968cd1c9c8e31..ff082acc694bdfd768c69ae95842c2182f1f0d75 100644 --- a/src/java.desktop/share/classes/javax/swing/JViewport.java +++ b/src/java.desktop/share/classes/javax/swing/JViewport.java @@ -565,7 +565,7 @@ public class JViewport extends JComponent implements Accessible * a JViewPort. * * @param border the Border to set - * @exception IllegalArgumentException this method is not implemented + * @throws IllegalArgumentException this method is not implemented */ public final void setBorder(Border border) { if (border != null) { diff --git a/src/java.desktop/share/classes/javax/swing/JWindow.java b/src/java.desktop/share/classes/javax/swing/JWindow.java index 69269c9f284ce1354a7fcadc6db024ee7192f483..a306ea6d4ea1b95e2291032005d4583e25a2afbf 100644 --- a/src/java.desktop/share/classes/javax/swing/JWindow.java +++ b/src/java.desktop/share/classes/javax/swing/JWindow.java @@ -387,10 +387,10 @@ public class JWindow extends Window implements Accessible, * @param comp the component to be enhanced * @param constraints the constraints to be respected * @param index the index - * @exception IllegalArgumentException if index is invalid - * @exception IllegalArgumentException if adding the container's parent + * @throws IllegalArgumentException if index is invalid + * @throws IllegalArgumentException if adding the container's parent * to itself - * @exception IllegalArgumentException if adding a window to a container + * @throws IllegalArgumentException if adding a window to a container * * @see #setRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer @@ -504,7 +504,7 @@ public class JWindow extends Window implements Accessible, * * @param contentPane the new contentPane * - * @exception IllegalComponentStateException (a runtime + * @throws IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see #getContentPane * @see RootPaneContainer#setContentPane @@ -532,7 +532,7 @@ public class JWindow extends Window implements Accessible, * * @param layeredPane the new layeredPane object * - * @exception IllegalComponentStateException (a runtime + * @throws IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see #getLayeredPane * @see RootPaneContainer#setLayeredPane diff --git a/src/java.desktop/share/classes/javax/swing/OverlayLayout.java b/src/java.desktop/share/classes/javax/swing/OverlayLayout.java index 0067f6fd6bd54bab9fe7b8461f4917852bcc1579..71ca34f1aa069ab14f5c2d49310d8e18b45c808c 100644 --- a/src/java.desktop/share/classes/javax/swing/OverlayLayout.java +++ b/src/java.desktop/share/classes/javax/swing/OverlayLayout.java @@ -217,7 +217,7 @@ public class OverlayLayout implements LayoutManager2,Serializable { * * @param target the container to lay out * - * @exception AWTError if the target isn't the container specified to the + * @throws AWTError if the target isn't the container specified to the * constructor */ public void layoutContainer(Container target) { diff --git a/src/java.desktop/share/classes/javax/swing/Popup.java b/src/java.desktop/share/classes/javax/swing/Popup.java index 605ecd6fd78099b72d97f605246788da84c9de0a..15c90ad3be775215efc26bc6b7dd3e44020425f2 100644 --- a/src/java.desktop/share/classes/javax/swing/Popup.java +++ b/src/java.desktop/share/classes/javax/swing/Popup.java @@ -82,7 +82,7 @@ public class Popup { * @param contents Contents of the Popup * @param x Initial x screen coordinate * @param y Initial y screen coordinate - * @exception IllegalArgumentException if contents is null + * @throws IllegalArgumentException if contents is null */ protected Popup(Component owner, Component contents, int x, int y) { this(); diff --git a/src/java.desktop/share/classes/javax/swing/PopupFactory.java b/src/java.desktop/share/classes/javax/swing/PopupFactory.java index 462675fa828587cbe6b08bc2f35151a32b4d9fa4..a30aba6f2fc0a6d359f997c619bdb76567ad0930 100644 --- a/src/java.desktop/share/classes/javax/swing/PopupFactory.java +++ b/src/java.desktop/share/classes/javax/swing/PopupFactory.java @@ -127,7 +127,7 @@ public class PopupFactory { * factory is null. * * @param factory Shared PopupFactory - * @exception IllegalArgumentException if factory is null + * @throws IllegalArgumentException if factory is null * @see #getPopup */ public static void setSharedInstance(PopupFactory factory) { @@ -186,7 +186,7 @@ public class PopupFactory { * @param contents Contents of the Popup * @param x Initial x screen coordinate * @param y Initial y screen coordinate - * @exception IllegalArgumentException if contents is null + * @throws IllegalArgumentException if contents is null * @return Popup containing Contents */ public Popup getPopup(Component owner, Component contents, diff --git a/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java b/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java index 8733d5b3cfef510a19889614ae5ff76e41f43f39..6f2d1eda4b674a4899e0b8d9adb39b440709c343 100644 --- a/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java +++ b/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java @@ -794,7 +794,7 @@ public class ProgressMonitor implements 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/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index fe414fc16afcd5f965ce676b985a691d82edac25..3831a66a01c4ead0bd413b13180bdbe26d46a8d9 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -966,7 +966,7 @@ public class RepaintManager tmp.setBounds(dirtyComponents.get(dirtyComponent)); // System.out.println("Collect dirty component for bound " + tmp + - // "component bounds is " + cBounds);; + // "component bounds is " + cBounds); SwingUtilities.computeIntersection(0,0,w,h,tmp); if (tmp.isEmpty()) { diff --git a/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java b/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java index 76dc2286f8725085cba8ce80a279f5150033a25d..b05e0c52e554784c2cb6ff6453d687c3b920cf0b 100644 --- a/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java +++ b/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java @@ -103,7 +103,7 @@ public interface RootPaneContainer * Generally implemented with * getRootPane().setContentPane(contentPane); * - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @param contentPane the Container to use for the contents of this * JRootPane @@ -134,7 +134,7 @@ public interface RootPaneContainer * getRootPane().setLayeredPane(layeredPane); * * @param layeredPane the layered pane - * @exception java.awt.IllegalComponentStateException (a runtime + * @throws java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null * @see #getLayeredPane * @see JRootPane#getLayeredPane diff --git a/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java b/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java index 9f9e66606664bbd0cb6cdd55fccefe71b3960a5b..0b8d8576f1469f1f60c25c36875599de1a91d973 100644 --- a/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java +++ b/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java @@ -230,7 +230,7 @@ public class ScrollPaneLayout * * @param s the component identifier * @param c the component to be added - * @exception IllegalArgumentException if s is an invalid key + * @throws IllegalArgumentException if s is an invalid key */ public void addLayoutComponent(String s, Component c) { @@ -328,7 +328,7 @@ public class ScrollPaneLayout * with the Swing 1.0.2 (and earlier) versions of this class. * * @param x an integer giving the display policy - * @exception IllegalArgumentException if x is an invalid + * @throws IllegalArgumentException if x is an invalid * vertical scroll bar policy, as listed above */ public void setVerticalScrollBarPolicy(int x) { @@ -366,7 +366,7 @@ public class ScrollPaneLayout * with the Swing 1.0.2 (and earlier) versions of this class. * * @param x an int giving the display policy - * @exception IllegalArgumentException if x is not a valid + * @throws IllegalArgumentException if x is not a valid * horizontal scrollbar policy, as listed above */ public void setHorizontalScrollBarPolicy(int x) { diff --git a/src/java.desktop/share/classes/javax/swing/SizeSequence.java b/src/java.desktop/share/classes/javax/swing/SizeSequence.java index 899a64570f3145d3ab0b51315cba10af4ebb6edf..c6877dc8b2b1b15ef75563017ba19fb9c3cd83d6 100644 --- a/src/java.desktop/share/classes/javax/swing/SizeSequence.java +++ b/src/java.desktop/share/classes/javax/swing/SizeSequence.java @@ -142,7 +142,7 @@ public class SizeSequence { * all initialized to have size 0. * * @param numEntries the number of sizes to track - * @exception NegativeArraySizeException if + * @throws NegativeArraySizeException if * numEntries < 0 */ public SizeSequence(int numEntries) { @@ -355,7 +355,7 @@ public class SizeSequence { * in the group * @param length the number of entries in the group * @param value the size to be assigned to each new entry - * @exception ArrayIndexOutOfBoundsException if the parameters + * @throws ArrayIndexOutOfBoundsException if the parameters * are outside of the range: * (0 <= start < (getSizes().length)) AND (length >= 0) */ diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index 5e3965e69b8edf7601ec495dd0c1aaefe251352a..1d58541dfee4f2e20a4173b329249b6f2446e01f 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -1466,10 +1466,10 @@ public class SwingUtilities implements SwingConstants * java.awt.EventQueue.invokeAndWait(). * * @param doRun the instance of {@code Runnable} - * @exception InterruptedException if we're interrupted while waiting for + * @throws InterruptedException if we're interrupted while waiting for * the event dispatching thread to finish executing * doRun.run() - * @exception InvocationTargetException if an exception is thrown + * @throws InvocationTargetException if an exception is thrown * while running doRun * * @see #invokeLater @@ -1984,7 +1984,7 @@ public class SwingUtilities implements SwingConstants * Returns a toolkit-private, shared, invisible Frame * to be the owner for JDialogs and JWindows created with * {@code null} owners. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -2002,7 +2002,7 @@ public class SwingUtilities implements SwingConstants /** * Returns a SharedOwnerFrame's shutdown listener to dispose the SharedOwnerFrame * if it has no more displayable children. - * @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/javax/swing/TablePrintable.java b/src/java.desktop/share/classes/javax/swing/TablePrintable.java index 4c8eb0529abd093d95d8fe5a3fb3cbcb0ae60f59..a6de3de2b09053c7e53c197d241263a6631b9ff6 100644 --- a/src/java.desktop/share/classes/javax/swing/TablePrintable.java +++ b/src/java.desktop/share/classes/javax/swing/TablePrintable.java @@ -395,11 +395,14 @@ class TablePrintable implements Printable { // draw a box around the table g2d.setColor(Color.BLACK); + Rectangle bounds = table.getBounds(); + bounds.x = bounds.y = 0; + // compute the visible portion of table and draw the rect around it - Rectangle visibleBounds = clip.intersection(table.getBounds()); + Rectangle visibleBounds = clip.intersection(bounds); Point upperLeft = visibleBounds.getLocation(); - Point lowerRight = new Point(visibleBounds.x + visibleBounds.width, - visibleBounds.y + visibleBounds.height); + Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1, + visibleBounds.y + visibleBounds.height - 1); int rMin = table.rowAtPoint(upperLeft); int rMax = table.rowAtPoint(lowerRight); @@ -410,7 +413,7 @@ class TablePrintable implements Printable { rMax = table.getRowCount(); } int rowHeight = 0; - for(int visrow = rMin; visrow < rMax; visrow++) { + for(int visrow = rMin; visrow <= rMax; visrow++) { rowHeight += table.getRowHeight(visrow); } // If PrintMode is FIT_WIDTH, then draw rect for entire column width while diff --git a/src/java.desktop/share/classes/javax/swing/Timer.java b/src/java.desktop/share/classes/javax/swing/Timer.java index 6b4f95be108038b04c2989d0cd6d393e97595f53..ced691f4e06d6398cd08dcce339fdcd9496bdcfa 100644 --- a/src/java.desktop/share/classes/javax/swing/Timer.java +++ b/src/java.desktop/share/classes/javax/swing/Timer.java @@ -341,7 +341,7 @@ public class Timer implements Serializable * on this timer, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType doesn't + * @throws ClassCastException if listenerType doesn't * specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/TransferHandler.java b/src/java.desktop/share/classes/javax/swing/TransferHandler.java index f2622880e7fa3e6576df41ee1f9bdc2e354f2444..445234e4bdab544bea5349cee36b18d69832ed42 100644 --- a/src/java.desktop/share/classes/javax/swing/TransferHandler.java +++ b/src/java.desktop/share/classes/javax/swing/TransferHandler.java @@ -1172,9 +1172,9 @@ public class TransferHandler implements Serializable { * * @param flavor the requested flavor for the data * @see DataFlavor#getRepresentationClass - * @exception IOException if the data is no longer available + * @throws IOException if the data is no longer available * in the requested flavor. - * @exception UnsupportedFlavorException if the requested data flavor is + * @throws UnsupportedFlavorException if the requested data flavor is * not supported. */ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { diff --git a/src/java.desktop/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java b/src/java.desktop/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java index 2f2163c89397b19e1aafe4e6c0e62b0392a2338c..9a42849251289866e0c0cb6a1aacd9408e7f2a51 100644 --- a/src/java.desktop/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java +++ b/src/java.desktop/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java @@ -161,7 +161,7 @@ public abstract class AbstractColorChooserPanel extends JPanel { * If you override this, be sure to call super. * * @param enclosingChooser the chooser to which the panel is to be added - * @exception RuntimeException if the chooser panel has already been + * @throws RuntimeException if the chooser panel has already been * installed */ public void installChooserPanel(JColorChooser enclosingChooser) { diff --git a/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java b/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java index 1be0228864c1e84410ef3138cbda74dc407aef99..81ae23930088de548cd41a41f61bd490b4122dc9 100644 --- a/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java +++ b/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java @@ -144,7 +144,7 @@ public class EventListenerList implements Serializable { * @param the type of {@code EventListener} to search for * @param t the type of {@code EventListener} classes to be returned * @return all of the listeners of the specified type. - * @exception ClassCastException if the supplied class + * @throws ClassCastException if the supplied class * is not assignable to EventListener * * @since 1.3 diff --git a/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java index cba6691ba58b7091c8db951004c8a299cea0f78e..3c96fdabffd641285c709b88670c38e2fb32eb87 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java @@ -49,7 +49,7 @@ public abstract class TextUI extends ComponentUI * @param t the text component for which this UI is installed * @param pos the local location in the model to translate >= 0 * @return the coordinates as a {@code Rectangle} - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * * @deprecated replaced by @@ -66,7 +66,7 @@ public abstract class TextUI extends ComponentUI * @param pos the local location in the model to translate >= 0 * @param bias the bias for the position * @return the coordinates as a {@code Rectangle} - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * * @deprecated replaced by @@ -86,7 +86,7 @@ public abstract class TextUI extends ComponentUI * @param pos the local location in the model to translate {@code >= 0} * @param bias the bias for the position * @return the coordinates as a {@code Rectangle2D} - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * * @since 9 @@ -178,8 +178,8 @@ public abstract class TextUI extends ComponentUI * @param biasRet an array to contain the bias for the returned position * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException for a bad location within a document model - * @exception IllegalArgumentException for an invalid direction + * @throws BadLocationException for a bad location within a document model + * @throws IllegalArgumentException for an invalid direction */ public abstract int getNextVisualPositionFrom(JTextComponent t, int pos, Position.Bias b, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java index 3e1108fb25bd2a6e005fc5f96651969936912055..5a7f88ff3cec4f59ab50b93fb2b691a2950918dd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java @@ -585,9 +585,9 @@ public class BasicHTML { * position is a boundary of two views. * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException for an invalid bias argument + * @throws IllegalArgumentException for an invalid bias argument * @see View#viewToModel */ public Shape modelToView(int p0, Position.Bias b0, int p1, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 360e98eee7af162de68e894798021356165e92ff..92d5896bca299a5986512cf630a81717b6bed261 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -775,7 +775,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { * Returns the baseline for the specified tab. * * @param tab index of tab to get baseline for - * @exception IndexOutOfBoundsException if index is out of range + * @throws IndexOutOfBoundsException if index is out of range * (index < 0 || index >= tab count) * @return baseline or a value < 0 indicating there is no reasonable * baseline diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java index 37ebb12823cd71ddd5f1429481a5908fbb06b595..59f966df2c3c09dba1647b0cfe6c7142972978aa 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java @@ -1872,23 +1872,6 @@ public class BasicTableUI extends TableUI comp = comp.getParent(); } - if (comp != null && !(comp instanceof JViewport) && !(comp instanceof JScrollPane)) { - // We did rMax-1 to paint the same number of rows that are drawn on console - // otherwise 1 extra row is printed per page than that are displayed - // when there is no scrollPane and we do printing of table - // but not when rmax is already pointing to index of last row - // and if there is any selected rows - if (rMax != (table.getRowCount() - 1) && - (table.getSelectedRow() == -1)) { - // Do not decrement rMax if rMax becomes - // less than or equal to rMin - // else cells will not be painted - if (rMax - rMin > 1) { - rMax = rMax - 1; - } - } - } - // Paint the grid. paintGrid(g, rMin, rMax, cMin, cMax); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java index 2e67a99720a58451422a177acb6cccb919fcbe96..5d767d3b7034c81ad9a12b87536033d4c7783faa 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -345,7 +345,7 @@ public class BasicTextFieldUI extends BasicTextUI { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ @@ -367,9 +367,9 @@ public class BasicTextFieldUI extends BasicTextUI { * position is a boundary of two views. * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException for an invalid bias argument + * @throws IllegalArgumentException for an invalid bias argument * @see View#viewToModel */ public Shape modelToView(int p0, Position.Bias b0, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 6e98a57e5c31d266480b29822fe60203cdf961fc..881b9557b0c9909e4a593bef74987d6005459206 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1045,7 +1045,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { * @param tc the text component for which this UI is installed * @param pos the local location in the model to translate >= 0 * @return the coordinates as a rectangle, null if the model is not painted - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView * @@ -1067,7 +1067,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { * @param tc the text component for which this UI is installed * @param pos the local location in the model to translate >= 0 * @return the coordinates as a rectangle, null if the model is not painted - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView * @@ -1626,9 +1626,9 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { * position is a boundary of two views. * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException for an invalid bias argument + * @throws IllegalArgumentException for an invalid bias argument * @see View#viewToModel */ public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { @@ -1674,9 +1674,9 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { * SwingConstants.NORTH, or SwingConstants.SOUTH. * @return the location within the model that best represents the next * location visual position. - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document - * @exception IllegalArgumentException for an invalid direction + * @throws IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTransferable.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTransferable.java index 544c2ebe73115e55bea3cbfa2d1325cc6fac0939..116226188c9da4ae9952ba95848723b53870ae63 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTransferable.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTransferable.java @@ -130,9 +130,9 @@ class BasicTransferable implements Transferable, UIResource { * * @param flavor the requested flavor for the data * @see DataFlavor#getRepresentationClass - * @exception IOException if the data is no longer available + * @throws IOException if the data is no longer available * in the requested flavor. - * @exception UnsupportedFlavorException if the requested data flavor is + * @throws UnsupportedFlavorException if the requested data flavor is * not supported. */ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/ParsedSynthStyle.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/ParsedSynthStyle.java index 3173b40ab6a23622fa2dcea4d5da2e88309b8887..ff559ee1d4fa922651530f8e33bf1dcb8b5deb4a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/ParsedSynthStyle.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/ParsedSynthStyle.java @@ -1935,9 +1935,9 @@ class ParsedSynthStyle extends DefaultSynthStyle { } public void paintTabbedPaneTabBackground(SynthContext context, - Graphics g, int x, int y, int w, int h, int direction) { + Graphics g, int x, int y, int w, int h, int tabIndex) { getPainter(context, "tabbedpanetabbackground", -1). - paintTabbedPaneTabBackground(context, g, x, y, w, h, direction); + paintTabbedPaneTabBackground(context, g, x, y, w, h, tabIndex); } public void paintTabbedPaneTabBackground(SynthContext context, diff --git a/src/java.desktop/share/classes/javax/swing/table/AbstractTableModel.java b/src/java.desktop/share/classes/javax/swing/table/AbstractTableModel.java index 886d0ad64b02faf26c2cc8a6a7bc419a1e019456..99208f3cd266f41470d933722ecbd7bc8e9d68e7 100644 --- a/src/java.desktop/share/classes/javax/swing/table/AbstractTableModel.java +++ b/src/java.desktop/share/classes/javax/swing/table/AbstractTableModel.java @@ -331,7 +331,7 @@ public abstract class AbstractTableModel implements TableModel, Serializable * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/table/DefaultTableColumnModel.java b/src/java.desktop/share/classes/javax/swing/table/DefaultTableColumnModel.java index 71c39b7e8bb0bd75ca82d6aff68e6902930de372..e1a6264a4788ef0a279f58a8eb3d49cf003b3f99 100644 --- a/src/java.desktop/share/classes/javax/swing/table/DefaultTableColumnModel.java +++ b/src/java.desktop/share/classes/javax/swing/table/DefaultTableColumnModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, 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 @@ -109,7 +109,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * event to its listeners. * * @param aColumn the TableColumn to be added - * @exception IllegalArgumentException if aColumn is + * @throws IllegalArgumentException if aColumn is * null * @see #removeColumn */ @@ -170,7 +170,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * * @param columnIndex the index of column to be moved * @param newIndex new index to move the column - * @exception IllegalArgumentException if column or + * @throws IllegalArgumentException if column or * newIndex * are not in the valid range */ @@ -258,7 +258,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * @return the index of the first column in the * tableColumns array whose identifier * is equal to identifier - * @exception IllegalArgumentException if identifier + * @throws IllegalArgumentException if identifier * is null, or if no * TableColumn has this * identifier @@ -290,6 +290,9 @@ public class DefaultTableColumnModel implements TableColumnModel, * @param columnIndex the index of the column desired * @return the TableColumn object for the column * at columnIndex + * @throws ArrayIndexOutOfBoundsException if columnIndex + * is out of range: + * (columnIndex < 0 || columnIndex >= getColumnCount()) */ public TableColumn getColumn(int columnIndex) { return tableColumns.elementAt(columnIndex); @@ -365,7 +368,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * an exception is thrown. * * @param newModel the new selection model - * @exception IllegalArgumentException if newModel + * @throws IllegalArgumentException if newModel * is null * @see #getSelectionModel */ @@ -633,7 +636,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * FooListeners on this model, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java b/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java index 08dfc85b0a961ea795bc2aedbf7f991cdfb28237..cdb3f29b76a11efe3f7a78b1590560ecdea5794f 100644 --- a/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java +++ b/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java @@ -375,7 +375,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * * @param row the row index of the row to be inserted * @param rowData optional data of the row being added - * @exception ArrayIndexOutOfBoundsException if the row was invalid + * @throws ArrayIndexOutOfBoundsException if the row was invalid */ public void insertRow(int row, Vector rowData) { dataVector.insertElementAt(rowData, row); @@ -390,7 +390,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * * @param row the row index of the row to be inserted * @param rowData optional data of the row being added - * @exception ArrayIndexOutOfBoundsException if the row was invalid + * @throws ArrayIndexOutOfBoundsException if the row was invalid */ public void insertRow(int row, Object[] rowData) { insertRow(row, convertToVector(rowData)); @@ -438,7 +438,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param start the starting row index to be moved * @param end the ending row index to be moved * @param to the destination of the rows to be moved - * @exception ArrayIndexOutOfBoundsException if any of the elements + * @throws ArrayIndexOutOfBoundsException if any of the elements * would be moved out of the table's range * */ @@ -463,7 +463,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * of the row being removed will be sent to all the listeners. * * @param row the row index of the row to be removed - * @exception ArrayIndexOutOfBoundsException if the row was invalid + * @throws ArrayIndexOutOfBoundsException if the row was invalid */ public void removeRow(int row) { dataVector.removeElementAt(row); @@ -652,7 +652,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param row the row whose value is to be queried * @param column the column whose value is to be queried * @return the value Object at the specified cell - * @exception ArrayIndexOutOfBoundsException if an invalid row or + * @throws ArrayIndexOutOfBoundsException if an invalid row or * column was given */ public Object getValueAt(int row, int column) { @@ -669,7 +669,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param aValue the new value; this can be null * @param row the row whose value is to be changed * @param column the column whose value is to be changed - * @exception ArrayIndexOutOfBoundsException if an invalid row or + * @throws ArrayIndexOutOfBoundsException if an invalid row or * column was given */ public void setValueAt(Object aValue, int row, int column) { diff --git a/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java b/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java index f36b5646e3d4ffc22728865f8eb171863d8c3ce9..561d6a71c75493b962a6447e30cfbf731c36c3b6 100644 --- a/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java +++ b/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java @@ -550,7 +550,7 @@ public class JTableHeader extends JComponent implements TableColumnModelListener * for listener notifications from the new column model. * * @param columnModel the new data source for this table - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if newModel is null * @see #getColumnModel */ diff --git a/src/java.desktop/share/classes/javax/swing/table/TableColumnModel.java b/src/java.desktop/share/classes/javax/swing/table/TableColumnModel.java index eaaa8447ef701f93ce3b08aeef3a0c9f5c109c32..4cf4870b5e3543787deb710cb20c927fc3374627 100644 --- a/src/java.desktop/share/classes/javax/swing/table/TableColumnModel.java +++ b/src/java.desktop/share/classes/javax/swing/table/TableColumnModel.java @@ -79,7 +79,7 @@ public interface TableColumnModel * * @param columnIndex the index of column to be moved * @param newIndex index of the column's new location - * @exception IllegalArgumentException if columnIndex or + * @throws IllegalArgumentException if columnIndex or * newIndex * are not in the valid range */ @@ -119,7 +119,7 @@ public interface TableColumnModel * @param columnIdentifier the identifier object * @return the index of the first table column * whose identifier is equal to identifier - * @exception IllegalArgumentException if identifier + * @throws IllegalArgumentException if identifier * is null, or no * TableColumn has this * identifier diff --git a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java index 1b97006bc34723021fef05e40aad70554481f4c5..db19b81e8e50471cb04fb52d0e3e08e4b19230da 100644 --- a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java @@ -344,7 +344,7 @@ public abstract class AbstractDocument implements Document, Serializable { * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * @@ -604,7 +604,7 @@ public abstract class AbstractDocument implements Document, Serializable { * * @param offs the starting offset >= 0 * @param len the number of characters to remove >= 0 - * @exception BadLocationException the given remove position is not a valid + * @throws BadLocationException the given remove position is not a valid * position within the document * @see Document#remove */ @@ -674,7 +674,7 @@ public abstract class AbstractDocument implements Document, Serializable { * null * is legal, and typically treated as an empty attributeset, * but exact interpretation is left to the subclass - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document * @since 1.4 */ @@ -718,7 +718,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @param offs the starting offset >= 0 * @param str the string to insert; does nothing with null/empty strings * @param a the attributes for the inserted content - * @exception BadLocationException the given insert position is not a valid + * @throws BadLocationException the given insert position is not a valid * position within the document * @see Document#insertString */ @@ -792,7 +792,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @param offset the starting offset >= 0 * @param length the number of characters to retrieve >= 0 * @return the text - * @exception BadLocationException the range given includes a position + * @throws BadLocationException the range given includes a position * that is not a valid position within the document * @see Document#getText */ @@ -833,7 +833,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @param offset the starting offset >= 0 * @param length the number of characters to retrieve >= 0 * @param txt the Segment object to retrieve the text into - * @exception BadLocationException the range given includes a position + * @throws BadLocationException the range given includes a position * that is not a valid position within the document */ public void getText(int offset, int length, Segment txt) throws BadLocationException { @@ -854,7 +854,7 @@ public abstract class AbstractDocument implements Document, Serializable { * * @param offs the position in the model >= 0 * @return the position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see Document#createPosition */ @@ -1354,7 +1354,7 @@ public abstract class AbstractDocument implements Document, Serializable { * Document will be left in a locked state so that no * reading or writing can be done. * - * @exception IllegalStateException thrown on illegal lock + * @throws IllegalStateException thrown on illegal lock * attempt. If the document is implemented properly, this can * only happen if a document listener attempts to mutate the * document. This situation violates the bean event model @@ -1633,7 +1633,7 @@ public abstract class AbstractDocument implements Document, Serializable { * * @param offset the offset in the content >= 0 * @return a Position - * @exception BadLocationException for an invalid offset + * @throws BadLocationException for an invalid offset */ public Position createPosition(int offset) throws BadLocationException; @@ -1652,7 +1652,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @return if the implementation supports a history mechanism, * a reference to an Edit implementation will be returned, * otherwise returns null - * @exception BadLocationException thrown if the area covered by + * @throws BadLocationException thrown if the area covered by * the arguments is not contained in the character sequence */ public UndoableEdit insertString(int where, String str) throws BadLocationException; @@ -1666,7 +1666,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @return If the implementation supports a history mechanism, * a reference to an Edit implementation will be returned, * otherwise null. - * @exception BadLocationException Thrown if the area covered by + * @throws BadLocationException Thrown if the area covered by * the arguments is not contained in the character sequence. */ public UndoableEdit remove(int where, int nitems) throws BadLocationException; @@ -1677,7 +1677,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @param where Offset into the sequence to fetch >= 0. * @param len number of characters to copy >= 0. * @return the string - * @exception BadLocationException Thrown if the area covered by + * @throws BadLocationException Thrown if the area covered by * the arguments is not contained in the character sequence. */ public String getString(int where, int len) throws BadLocationException; @@ -1688,7 +1688,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @param where the starting offset >= 0 * @param len the number of characters >= 0 * @param txt the target location to copy into - * @exception BadLocationException Thrown if the area covered by + * @throws BadLocationException Thrown if the area covered by * the arguments is not contained in the character sequence. */ public void getChars(int where, int len, Segment txt) throws BadLocationException; @@ -2819,7 +2819,7 @@ public abstract class AbstractDocument implements Document, Serializable { /** * Redoes a change. * - * @exception CannotRedoException if the change cannot be redone + * @throws CannotRedoException if the change cannot be redone */ public void redo() throws CannotRedoException { writeLock(); @@ -2843,7 +2843,7 @@ public abstract class AbstractDocument implements Document, Serializable { /** * Undoes a change. * - * @exception CannotUndoException if the change cannot be undone + * @throws CannotUndoException if the change cannot be undone */ public void undo() throws CannotUndoException { writeLock(); @@ -3187,7 +3187,7 @@ public abstract class AbstractDocument implements Document, Serializable { /** * Redoes a change. * - * @exception CannotRedoException if the change cannot be redone + * @throws CannotRedoException if the change cannot be redone */ public void redo() throws CannotRedoException { super.redo(); @@ -3204,7 +3204,7 @@ public abstract class AbstractDocument implements Document, Serializable { /** * Undoes a change. * - * @exception CannotUndoException if the change cannot be undone + * @throws CannotUndoException if the change cannot be undone */ public void undo() throws CannotUndoException { super.undo(); diff --git a/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java b/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java index 0ca0fecb5a845fc33616b35b175cdce1df1e7c55..07a8301f0b5e4aebbe4e932d48a21f82e089c2cd 100644 --- a/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java +++ b/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java @@ -270,7 +270,7 @@ public abstract class AbstractWriter { * when encountered. * * @param elem an Element - * @exception BadLocationException if pos represents an invalid + * @throws BadLocationException if pos represents an invalid * location within the document * @return the text as a String */ @@ -286,8 +286,8 @@ public abstract class AbstractWriter { * out. * * @param elem an Element. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void text(Element elem) throws BadLocationException, @@ -462,7 +462,7 @@ public abstract class AbstractWriter { * line is empty, this will not make it so that the current line is * still considered empty. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void indent() throws IOException { int max = getIndentLevel() * getIndentSpace(); @@ -485,7 +485,7 @@ public abstract class AbstractWriter { * the write method that takes a char[]. * * @param ch a char. - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void write(char ch) throws IOException { if (tempChars == null) { @@ -500,7 +500,7 @@ public abstract class AbstractWriter { * write method that takes a char[]. * * @param content a String. - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void write(String content) throws IOException { if (content == null) { @@ -671,7 +671,7 @@ public abstract class AbstractWriter { * pairs. It throws an IOException when encountered. * * @param attr an AttributeSet. - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeAttributes(AttributeSet attr) throws IOException { diff --git a/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java b/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java index a9e4c58fbaa931e5911bbb29db58c7b6af1b43bc..ac0dd40b28a6f6607c2cb472ab370198298c0beb 100644 --- a/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java +++ b/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java @@ -640,7 +640,7 @@ public class AsyncBoxView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getPreferredSpan(int axis) { float margin = getInsetSpan(axis); @@ -665,7 +665,7 @@ public class AsyncBoxView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMinimumSpan(int axis) { if (axis == this.axis) { @@ -693,7 +693,7 @@ public class AsyncBoxView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMaximumSpan(int axis) { if (axis == this.axis) { @@ -773,9 +773,9 @@ public class AsyncBoxView extends View { * next character represented by the offset, in case the * position is a boundary of two views. * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException for an invalid bias argument + * @throws IllegalArgumentException for an invalid bias argument * @see View#viewToModel */ public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { @@ -864,9 +864,9 @@ public class AsyncBoxView extends View { * @param biasRet an array contain the bias that was checked * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document - * @exception IllegalArgumentException if direction is invalid + * @throws IllegalArgumentException if direction is invalid */ public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, diff --git a/src/java.desktop/share/classes/javax/swing/text/BoxView.java b/src/java.desktop/share/classes/javax/swing/text/BoxView.java index afaefacccf5457dcf74c8cfdcf67a4c6e06cf99b..cc21e03902173279df746ef44f86d0d619e2218e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/BoxView.java +++ b/src/java.desktop/share/classes/javax/swing/text/BoxView.java @@ -293,7 +293,7 @@ public class BoxView extends CompositeView { * @param axis may be either View.X_AXIS or * View.Y_AXIS * @return the weight - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public int getResizeWeight(int axis) { checkRequests(axis); @@ -473,7 +473,7 @@ public class BoxView extends CompositeView { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document * @see View#modelToView */ @@ -519,7 +519,7 @@ public class BoxView extends CompositeView { * origin and 1.0 indicates alignment to the full span * away from the origin; an alignment of 0.5 would be the * center of the view - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getAlignment(int axis) { checkRequests(axis); @@ -540,7 +540,7 @@ public class BoxView extends CompositeView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getPreferredSpan(int axis) { checkRequests(axis); @@ -563,7 +563,7 @@ public class BoxView extends CompositeView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMinimumSpan(int axis) { checkRequests(axis); @@ -586,7 +586,7 @@ public class BoxView extends CompositeView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMaximumSpan(int axis) { checkRequests(axis); @@ -919,7 +919,7 @@ public class BoxView extends CompositeView { /** * Checks the request cache and update if needed. * @param axis the axis being studied - * @exception IllegalArgumentException if axis is + * @throws IllegalArgumentException if axis is * neither View.X_AXIS nor View.Y_AXIS */ void checkRequests(int axis) { diff --git a/src/java.desktop/share/classes/javax/swing/text/ComponentView.java b/src/java.desktop/share/classes/javax/swing/text/ComponentView.java index a4aaa30e512bcc585064331d7b8f9de209a54735..0d8743f86edad48cebe44313e9a291cad5408f2e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/ComponentView.java +++ b/src/java.desktop/share/classes/javax/swing/text/ComponentView.java @@ -132,7 +132,7 @@ public class ComponentView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getPreferredSpan(int axis) { if ((axis != X_AXIS) && (axis != Y_AXIS)) { @@ -160,7 +160,7 @@ public class ComponentView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getMinimumSpan(int axis) { if ((axis != X_AXIS) && (axis != Y_AXIS)) { @@ -188,7 +188,7 @@ public class ComponentView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getMaximumSpan(int axis) { if ((axis != X_AXIS) && (axis != Y_AXIS)) { @@ -325,7 +325,7 @@ public class ComponentView extends View { * @param pos the position to convert >=0 * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/CompositeView.java b/src/java.desktop/share/classes/javax/swing/text/CompositeView.java index 343c02feddc17be09cd220ef71e32e1dd87be07a..5220395d35ad05fb2615d3ff92d9768f27c1b433 100644 --- a/src/java.desktop/share/classes/javax/swing/text/CompositeView.java +++ b/src/java.desktop/share/classes/javax/swing/text/CompositeView.java @@ -244,7 +244,7 @@ public abstract class CompositeView extends View { * @param b a bias value of either Position.Bias.Forward * or Position.Bias.Backward * @return the bounding box of the given position - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document * @see View#modelToView */ @@ -294,9 +294,9 @@ public abstract class CompositeView extends View { * position is a boundary of two views * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException for an invalid bias argument + * @throws IllegalArgumentException for an invalid bias argument * @see View#viewToModel */ public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { @@ -458,9 +458,9 @@ public abstract class CompositeView extends View { * @param biasRet an array containing the bias that was checked * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document - * @exception IllegalArgumentException if direction is invalid + * @throws IllegalArgumentException if direction is invalid */ public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) @@ -715,8 +715,8 @@ public abstract class CompositeView extends View { * @param biasRet an array containing the bias that was checked * @return the location within the model that best represents the next * north or south location - * @exception BadLocationException for a bad location within a document model - * @exception IllegalArgumentException if direction is invalid + * @throws BadLocationException for a bad location within a document model + * @throws IllegalArgumentException if direction is invalid * @see #getNextVisualPositionFrom */ protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b, @@ -748,8 +748,8 @@ public abstract class CompositeView extends View { * @param biasRet an array containing the bias that was checked * @return the location within the model that best represents the next * west or east location - * @exception BadLocationException for a bad location within a document model - * @exception IllegalArgumentException if direction is invalid + * @throws BadLocationException for a bad location within a document model + * @throws IllegalArgumentException if direction is invalid * @see #getNextVisualPositionFrom */ protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b, diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java b/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java index a980268bd941d503ffa44a23386abc6cebb86b0e..ff4d37224e370f9f3fa43a694503aa1d7e958466 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java @@ -870,7 +870,7 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java index ee1db4739ceaf27c0b8c72ecdb5c3a802b2c9135..2d9971d3794300630524e3c92ebae0f89550a5e8 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java @@ -142,8 +142,8 @@ public class DefaultEditorKit extends EditorKit { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >=0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void read(InputStream in, Document doc, int pos) @@ -161,8 +161,8 @@ public class DefaultEditorKit extends EditorKit { * @param pos The location in the document to fetch the * content >=0. * @param len The amount to write out >=0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void write(OutputStream out, Document doc, int pos, int len) @@ -193,8 +193,8 @@ public class DefaultEditorKit extends EditorKit { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >=0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void read(Reader in, Document doc, int pos) @@ -303,8 +303,8 @@ public class DefaultEditorKit extends EditorKit { * @param pos The location in the document to fetch the * content from >=0. * @param len The amount to write out >=0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos is not within 0 and + * @throws IOException on any I/O error + * @throws BadLocationException if pos is not within 0 and * the length of the document. */ public void write(Writer out, Document doc, int pos, int len) diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultHighlighter.java b/src/java.desktop/share/classes/javax/swing/text/DefaultHighlighter.java index 4e874ec1f007433bff147c63cd7ab12889161afb..0465b9157e28f959a68041861eb69c132fef5a12 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultHighlighter.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultHighlighter.java @@ -110,7 +110,7 @@ public class DefaultHighlighter extends LayeredHighlighter { * @param p the painter to use to actually render the highlight * @return an object that can be used as a tag * to refer to the highlight - * @exception BadLocationException if the specified location is invalid + * @throws BadLocationException if the specified location is invalid */ public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter p) throws BadLocationException { if (p0 < 0) { @@ -222,7 +222,7 @@ public class DefaultHighlighter extends LayeredHighlighter { * @param tag the highlight tag * @param p0 the beginning of the range >= 0 * @param p1 the end of the range >= p0 - * @exception BadLocationException if the specified location is invalid + * @throws BadLocationException if the specified location is invalid */ public void changeHighlight(Object tag, int p0, int p1) throws BadLocationException { if (p0 < 0) { diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java index f549f522ff2b7513449091c0a64ca8aebe4636ac..5d373177eaf0b96295e672c2bfaaa3da3c8a41b9 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -182,7 +182,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc * * @param offset the starting offset >= 0 * @param data the element data - * @exception BadLocationException for an invalid starting offset + * @throws BadLocationException for an invalid starting offset */ protected void insert(int offset, ElementSpec[] data) throws BadLocationException { if (data == null || data.length == 0) { @@ -2548,7 +2548,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc /** * Redoes a change. * - * @exception CannotRedoException if the change cannot be redone + * @throws CannotRedoException if the change cannot be redone */ public void redo() throws CannotRedoException { super.redo(); @@ -2562,7 +2562,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc /** * Undoes a change. * - * @exception CannotUndoException if the change cannot be undone + * @throws CannotUndoException if the change cannot be undone */ public void undo() throws CannotUndoException { super.undo(); @@ -2604,7 +2604,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc /** * Redoes a change. * - * @exception CannotRedoException if the change cannot be redone + * @throws CannotRedoException if the change cannot be redone */ public void redo() throws CannotRedoException { super.redo(); @@ -2614,7 +2614,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc /** * Undoes a change. * - * @exception CannotUndoException if the change cannot be undone + * @throws CannotUndoException if the change cannot be undone */ public void undo() throws CannotUndoException { super.undo(); diff --git a/src/java.desktop/share/classes/javax/swing/text/Document.java b/src/java.desktop/share/classes/javax/swing/text/Document.java index e0f4ac791d5e8962a593fcb51f8dea61351cef15..09f162733cfcb97bd959e44827c11bb0690e1d83 100644 --- a/src/java.desktop/share/classes/javax/swing/text/Document.java +++ b/src/java.desktop/share/classes/javax/swing/text/Document.java @@ -453,7 +453,7 @@ public interface Document { * * @param offs the offset from the beginning >= 0 * @param len the number of characters to remove >= 0 - * @exception BadLocationException some portion of the removal range + * @throws BadLocationException some portion of the removal range * was not a valid part of the document. The location in the exception * is the first bad position encountered. * @see javax.swing.event.DocumentEvent @@ -490,7 +490,7 @@ public interface Document { * @param str the string to insert * @param a the attributes to associate with the inserted * content. This may be null if there are no attributes. - * @exception BadLocationException the given insert position is not a valid + * @throws BadLocationException the given insert position is not a valid * position within the document * @see javax.swing.event.DocumentEvent * @see javax.swing.event.DocumentListener @@ -507,7 +507,7 @@ public interface Document { * start of the text >= 0 * @param length the length of the desired string >= 0 * @return the text, in a String of length >= 0 - * @exception BadLocationException some portion of the given range + * @throws BadLocationException some portion of the given range * was not a valid part of the document. The location in the exception * is the first bad position encountered. */ @@ -546,7 +546,7 @@ public interface Document { * @param length the length of the desired string >= 0 * @param txt the Segment object to return the text in * - * @exception BadLocationException Some portion of the given range + * @throws BadLocationException Some portion of the given range * was not a valid part of the document. The location in the exception * is the first bad position encountered. */ @@ -582,7 +582,7 @@ public interface Document { * * @param offs the offset from the start of the document >= 0 * @return the position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document */ public Position createPosition(int offs) throws BadLocationException; diff --git a/src/java.desktop/share/classes/javax/swing/text/DocumentFilter.java b/src/java.desktop/share/classes/javax/swing/text/DocumentFilter.java index 5f69882ff8ef9733f66560f0ad1aa21071bcc342..d0334bce45e11a324d515c45d1dfb19f1bcc8f78 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DocumentFilter.java +++ b/src/java.desktop/share/classes/javax/swing/text/DocumentFilter.java @@ -75,7 +75,7 @@ public class DocumentFilter { * @param fb FilterBypass that can be used to mutate Document * @param offset the offset from the beginning >= 0 * @param length the number of characters to remove >= 0 - * @exception BadLocationException some portion of the removal range + * @throws BadLocationException some portion of the removal range * was not a valid part of the document. The location in the exception * is the first bad position encountered. */ @@ -97,7 +97,7 @@ public class DocumentFilter { * @param string the string to insert * @param attr the attributes to associate with the inserted * content. This may be null if there are no attributes. - * @exception BadLocationException the given insert position is not a + * @throws BadLocationException the given insert position is not a * valid position within the document */ public void insertString(FilterBypass fb, int offset, String string, @@ -117,7 +117,7 @@ public class DocumentFilter { * @param text Text to insert, null indicates no text to insert * @param attrs AttributeSet indicating attributes of inserted text, * null is legal. - * @exception BadLocationException the given insert position is not a + * @throws BadLocationException the given insert position is not a * valid position within the document */ public void replace(FilterBypass fb, int offset, int length, String text, @@ -153,7 +153,7 @@ public class DocumentFilter { * * @param offset the offset from the beginning >= 0 * @param length the number of characters to remove >= 0 - * @exception BadLocationException some portion of the removal range + * @throws BadLocationException some portion of the removal range * was not a valid part of the document. The location in the * exception is the first bad position encountered. */ @@ -169,7 +169,7 @@ public class DocumentFilter { * @param string the string to insert * @param attr the attributes to associate with the inserted * content. This may be null if there are no attributes. - * @exception BadLocationException the given insert position is not a + * @throws BadLocationException the given insert position is not a * valid position within the document */ public abstract void insertString(int offset, String string, @@ -186,7 +186,7 @@ public class DocumentFilter { * @param string Text to insert, null indicates no text to insert * @param attrs AttributeSet indicating attributes of inserted text, * null is legal. - * @exception BadLocationException the given insert is not a + * @throws BadLocationException the given insert is not a * valid position within the document */ public abstract void replace(int offset, int length, String string, diff --git a/src/java.desktop/share/classes/javax/swing/text/EditorKit.java b/src/java.desktop/share/classes/javax/swing/text/EditorKit.java index 9163a6361e4cc3cc77a3fc153d170c97c241c9e1..cd491fb5bac4b5abff14c9c00129a65588b01051 100644 --- a/src/java.desktop/share/classes/javax/swing/text/EditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/EditorKit.java @@ -141,8 +141,8 @@ public abstract class EditorKit implements Cloneable, Serializable { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >= 0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public abstract void read(InputStream in, Document doc, int pos) @@ -157,8 +157,8 @@ public abstract class EditorKit implements Cloneable, Serializable { * @param pos The location in the document to fetch the * content from >= 0. * @param len The amount to write out >= 0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public abstract void write(OutputStream out, Document doc, int pos, int len) @@ -178,8 +178,8 @@ public abstract class EditorKit implements Cloneable, Serializable { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >= 0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public abstract void read(Reader in, Document doc, int pos) @@ -199,8 +199,8 @@ public abstract class EditorKit implements Cloneable, Serializable { * @param pos The location in the document to fetch the * content >= 0. * @param len The amount to write out >= 0. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public abstract void write(Writer out, Document doc, int pos, int len) diff --git a/src/java.desktop/share/classes/javax/swing/text/FieldView.java b/src/java.desktop/share/classes/javax/swing/text/FieldView.java index 936a78700beb40346c5bf38e1507c1b56eae4556..b5ad636994527f59113ebb51eb2b28c07961aff2 100644 --- a/src/java.desktop/share/classes/javax/swing/text/FieldView.java +++ b/src/java.desktop/share/classes/javax/swing/text/FieldView.java @@ -258,7 +258,7 @@ public class FieldView extends PlainView { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/GapContent.java b/src/java.desktop/share/classes/javax/swing/text/GapContent.java index c59c350541b117fad90cd1c992cb4d5fe88d5836..6c96b2b0ec3db8db94b91ebc0101385de3caabae 100644 --- a/src/java.desktop/share/classes/javax/swing/text/GapContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/GapContent.java @@ -130,7 +130,7 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S * @param where the starting position >= 0, < length() * @param str the non-null string to insert * @return an UndoableEdit object for undoing - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#insertString */ public UndoableEdit insertString(int where, String str) throws BadLocationException { @@ -148,7 +148,7 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S * @param where the starting position >= 0, where + nitems < length() * @param nitems the number of characters to remove >= 0 * @return an UndoableEdit object for undoing - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#remove */ public UndoableEdit remove(int where, int nitems) throws BadLocationException { @@ -168,7 +168,7 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S * @param where the starting position >= 0 * @param len the length to retrieve >= 0 * @return a string representing the content - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#getString */ public String getString(int where, int len) throws BadLocationException { @@ -186,7 +186,7 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S * @param where the starting position >= 0, where + len <= length() * @param len the number of characters to retrieve >= 0 * @param chars the Segment object to return the characters in - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#getChars */ public void getChars(int where, int len, Segment chars) throws BadLocationException { @@ -237,7 +237,7 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S * * @param offset the offset to track >= 0 * @return the position - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid */ public Position createPosition(int offset) throws BadLocationException { while ( queue.poll() != null ) { diff --git a/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java b/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java index 3a070bb4040f605712ffd4fbb9bc1087575871ac..59e2a9da491cff09b9c29de942560dc87e922289 100644 --- a/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java +++ b/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java @@ -231,8 +231,8 @@ class GlyphPainter2 extends GlyphView.GlyphPainter { * SwingConstants.NORTH, or SwingConstants.SOUTH. * @return the location within the model that best represents the next * location visual position. - * @exception BadLocationException - * @exception IllegalArgumentException for an invalid direction + * @throws BadLocationException + * @throws IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b, Shape a, diff --git a/src/java.desktop/share/classes/javax/swing/text/GlyphView.java b/src/java.desktop/share/classes/javax/swing/text/GlyphView.java index b075356593c595e667935f58a5d6846ada4b8aae..8a4828f62d54775aea6d64560722dddd8bbdfd82 100644 --- a/src/java.desktop/share/classes/javax/swing/text/GlyphView.java +++ b/src/java.desktop/share/classes/javax/swing/text/GlyphView.java @@ -637,7 +637,7 @@ public class GlyphView extends View implements TabableView, Cloneable { * @param b either Position.Bias.Forward * or Position.Bias.Backward * @return the bounding box of the given position - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ @@ -885,9 +885,9 @@ public class GlyphView extends View implements TabableView, Cloneable { * SwingConstants.NORTH, or SwingConstants.SOUTH. * @return the location within the model that best represents the next * location visual position. - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document - * @exception IllegalArgumentException for an invalid direction + * @throws IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, @@ -1199,7 +1199,7 @@ public class GlyphView extends View implements TabableView, Cloneable { * or Position.Bias.Backward * @param a Bounds of the View * @return the bounding box of the given position - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ @@ -1283,8 +1283,8 @@ public class GlyphView extends View implements TabableView, Cloneable { * is returned as the zero-th element of this array * @return the location within the model that best represents the next * location visual position. - * @exception BadLocationException for a bad location within a document model - * @exception IllegalArgumentException for an invalid direction + * @throws BadLocationException for a bad location within a document model + * @throws IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b, Shape a, int direction, diff --git a/src/java.desktop/share/classes/javax/swing/text/Highlighter.java b/src/java.desktop/share/classes/javax/swing/text/Highlighter.java index 10243f10cdd9b34d9e2e6a7c907bee56f0ccbd15..7913e47b948c28e232e89975be00d0b798948fc0 100644 --- a/src/java.desktop/share/classes/javax/swing/text/Highlighter.java +++ b/src/java.desktop/share/classes/javax/swing/text/Highlighter.java @@ -70,7 +70,7 @@ public interface Highlighter { * @param p1 the end of the range >= p0 * @param p the painter to use for the actual highlighting * @return an object that refers to the highlight - * @exception BadLocationException for an invalid range specification + * @throws BadLocationException for an invalid range specification */ public Object addHighlight(int p0, int p1, HighlightPainter p) throws BadLocationException; @@ -95,7 +95,7 @@ public interface Highlighter { * @param tag which highlight to change * @param p0 the beginning of the range >= 0 * @param p1 the end of the range >= p0 - * @exception BadLocationException for an invalid range specification + * @throws BadLocationException for an invalid range specification */ public void changeHighlight(Object tag, int p0, int p1) throws BadLocationException; diff --git a/src/java.desktop/share/classes/javax/swing/text/IconView.java b/src/java.desktop/share/classes/javax/swing/text/IconView.java index c908e973753cc385e1c8f2ba0c4b406a95a8f4e2..76cb653c9ae0d14484400b1c99dbfb46ac5f602b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/IconView.java +++ b/src/java.desktop/share/classes/javax/swing/text/IconView.java @@ -81,7 +81,7 @@ public class IconView extends View { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getPreferredSpan(int axis) { switch (axis) { @@ -123,7 +123,7 @@ public class IconView extends View { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java index cbdd308cc84b81dc0b516a9da0ad7d9d25e5105c..d618dc6a2a1989db5a22684e4d6e99340980c433 100644 --- a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java +++ b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java @@ -672,7 +672,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * component's {@code TransferHandler}. * * @param b whether or not to enable automatic drag handling - * @exception HeadlessException if + * @throws HeadlessException if * b is true and * GraphicsEnvironment.isHeadless() * returns true @@ -1358,7 +1358,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param offs the offset ≥ 0 * @param len the length ≥ 0 * @return the text - * @exception BadLocationException if the offset or length are invalid + * @throws BadLocationException if the offset or length are invalid */ public String getText(int offs, int len) throws BadLocationException { return getDocument().getText(offs, len); @@ -1376,7 +1376,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @return the coordinates as a rectangle, with (r.x, r.y) as the location * in the coordinate system, or null if the component does * not yet have a positive size. - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView * @@ -1400,7 +1400,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @return the coordinates as a rectangle, with (r.x, r.y) as the location * in the coordinate system, or null if the component does * not yet have a positive size. - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView2D * @@ -1545,7 +1545,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * an exception is thrown. * * @param pos the position - * @exception IllegalArgumentException if the value supplied + * @throws IllegalArgumentException if the value supplied * for position is less than zero or greater * than the component's text length * @see #setCaretPosition @@ -1617,7 +1617,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * of documents (such as html for example) might be * able to make use of this information; if non-null, * it is added as a property of the document - * @exception IOException as thrown by the stream being + * @throws IOException as thrown by the stream being * used to initialize * @see EditorKit#createDefaultDocument * @see #setDocument @@ -1643,7 +1643,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * text. * * @param out the output stream - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ public void write(Writer out) throws IOException { Document doc = getDocument(); @@ -1672,7 +1672,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * an exception is thrown. * * @param position the position - * @exception IllegalArgumentException if the value supplied + * @throws IllegalArgumentException if the value supplied * for position is less than zero or greater * than the component's text length */ @@ -1743,7 +1743,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * use DocumentListener. * * @return the text - * @exception NullPointerException if the document is null + * @throws NullPointerException if the document is null * @see #setText */ public String getText() { @@ -1763,7 +1763,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * null or the document empty, returns null. * * @return the text - * @exception IllegalArgumentException if the selection doesn't + * @throws IllegalArgumentException if the selection doesn't * have a valid mapping into the document for some reason * @see #setText */ @@ -2013,7 +2013,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param direction less than zero to scroll up/left, greater than * zero for down/right * @return the "unit" increment for scrolling in the specified direction - * @exception IllegalArgumentException for an invalid orientation + * @throws IllegalArgumentException for an invalid orientation * @see JScrollBar#setUnitIncrement */ public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { @@ -2043,7 +2043,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param direction less than zero to scroll up/left, greater than zero * for down/right * @return the "block" increment for scrolling in the specified direction - * @exception IllegalArgumentException for an invalid orientation + * @throws IllegalArgumentException for an invalid orientation * @see JScrollBar#setBlockIncrement */ public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { diff --git a/src/java.desktop/share/classes/javax/swing/text/NavigationFilter.java b/src/java.desktop/share/classes/javax/swing/text/NavigationFilter.java index 648625e8974f7b8e832412561aa4e99226105caa..a7d85a71e02d130cb67b4508862c0f1bccd1a22e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/NavigationFilter.java +++ b/src/java.desktop/share/classes/javax/swing/text/NavigationFilter.java @@ -105,8 +105,8 @@ public class NavigationFilter { * @param biasRet Used to return resulting Bias of next position * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException for a bad location within a document model - * @exception IllegalArgumentException if direction + * @throws BadLocationException for a bad location within a document model + * @throws IllegalArgumentException if direction * doesn't have one of the legal values above */ public int getNextVisualPositionFrom(JTextComponent text, int pos, diff --git a/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java b/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java index f8d0e390cb2a84e9c1f0042dcf213a8d70ddb80a..e24583af13b140a8ec5557169a34161549e21053 100644 --- a/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java +++ b/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java @@ -876,7 +876,7 @@ public class ParagraphView extends FlowView implements TabExpander { * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/PasswordView.java b/src/java.desktop/share/classes/javax/swing/text/PasswordView.java index 38bb0eec13ea1c1f0bf5daeb926ea454e192c0ca..bdf8d5cdfe64c6aedb7c7b03cdb7dc1fe04fc71f 100644 --- a/src/java.desktop/share/classes/javax/swing/text/PasswordView.java +++ b/src/java.desktop/share/classes/javax/swing/text/PasswordView.java @@ -61,7 +61,7 @@ public class PasswordView extends FieldView { * @param p0 the starting offset in the model >= 0 * @param p1 the ending offset in the model >= p0 * @return the X location of the end of the range >= 0 - * @exception BadLocationException if p0 or p1 are out of range + * @throws BadLocationException if p0 or p1 are out of range * * @deprecated replaced by * {@link #drawUnselectedText(Graphics2D, float, float, int, int)} @@ -131,7 +131,7 @@ public class PasswordView extends FieldView { * @param p0 the starting offset in the model >= 0 * @param p1 the ending offset in the model >= p0 * @return the X location of the end of the range >= 0 - * @exception BadLocationException if p0 or p1 are out of range + * @throws BadLocationException if p0 or p1 are out of range * * @deprecated replaced by * {@link #drawSelectedText(Graphics2D, float, float, int, int)} @@ -240,7 +240,7 @@ public class PasswordView extends FieldView { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/PlainDocument.java b/src/java.desktop/share/classes/javax/swing/text/PlainDocument.java index cd397d12a684b17707be2299a5c96f10d5a5d5d9..ad6a0bdf2d3e9b7448830fbcd979569db8bd2792 100644 --- a/src/java.desktop/share/classes/javax/swing/text/PlainDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/PlainDocument.java @@ -107,7 +107,7 @@ public class PlainDocument extends AbstractDocument { * @param offs the starting offset >= 0 * @param str the string to insert; does nothing with null/empty strings * @param a the attributes for the inserted content - * @exception BadLocationException the given insert position is not a valid + * @throws BadLocationException the given insert position is not a valid * position within the document * @see Document#insertString */ diff --git a/src/java.desktop/share/classes/javax/swing/text/PlainView.java b/src/java.desktop/share/classes/javax/swing/text/PlainView.java index 725dec9bb7dd783bb356b2f7392778638cc33693..0c245196d995420f2b8dd0cb786374ba3822d889 100644 --- a/src/java.desktop/share/classes/javax/swing/text/PlainView.java +++ b/src/java.desktop/share/classes/javax/swing/text/PlainView.java @@ -179,7 +179,7 @@ public class PlainView extends View implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= 0 * @return the X location of the end of the range >= 0 - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @deprecated replaced by * {@link #drawUnselectedText(Graphics2D, float, float, int, int)} @@ -224,7 +224,7 @@ public class PlainView extends View implements TabExpander { * @param p0 the beginning position in the model {@code >= 0} * @param p1 the ending position in the model {@code >= 0} * @return the X location of the end of the range {@code >= 0} - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @since 9 */ @@ -245,7 +245,7 @@ public class PlainView extends View implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= 0 * @return the location of the end of the range - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @deprecated replaced by * {@link #drawSelectedText(Graphics2D, float, float, int, int)} @@ -294,7 +294,7 @@ public class PlainView extends View implements TabExpander { * @param p0 the beginning position in the model {@code >= 0} * @param p1 the ending position in the model {@code >= 0} * @return the location of the end of the range - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @since 9 */ @@ -351,7 +351,7 @@ public class PlainView extends View implements TabExpander { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getPreferredSpan(int axis) { updateMetrics(); @@ -468,7 +468,7 @@ public class PlainView extends View implements TabExpander { * @param pos the position to convert >= 0 * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/StringContent.java b/src/java.desktop/share/classes/javax/swing/text/StringContent.java index 7f154df38edffce7203667f93ff9980c0c6268ba..04bd4d7e0b464880b01f3857a57fd6c7c1cb6a8b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StringContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/StringContent.java @@ -90,7 +90,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab * @param where the starting position >= 0 && < length() * @param str the non-null string to insert * @return an UndoableEdit object for undoing - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#insertString */ public UndoableEdit insertString(int where, String str) throws BadLocationException { @@ -111,7 +111,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab * @param where the starting position >= 0 * @param nitems the number of characters to remove >= 0 * @return an UndoableEdit object for undoing - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#remove */ public UndoableEdit remove(int where, int nitems) throws BadLocationException { @@ -134,7 +134,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab * @param where the starting position >= 0 * @param len the length to retrieve >= 0 * @return a string representing the content; may be empty - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#getString */ public String getString(int where, int len) throws BadLocationException { @@ -150,7 +150,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab * @param where the starting position >= 0 * @param len the number of characters to retrieve >= 0 * @param chars the Segment object to return the characters in - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid * @see AbstractDocument.Content#getChars */ public void getChars(int where, int len, Segment chars) throws BadLocationException { @@ -168,7 +168,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab * * @param offset the offset to create a position for >= 0 * @return the position - * @exception BadLocationException if the specified position is invalid + * @throws BadLocationException if the specified position is invalid */ public Position createPosition(int offset) throws BadLocationException { // some small documents won't have any sticky positions diff --git a/src/java.desktop/share/classes/javax/swing/text/StyleContext.java b/src/java.desktop/share/classes/javax/swing/text/StyleContext.java index 9e01aecd3fb6dc3c5cef3abdfdebf0368cf9c77f..70da1356b99557b11cb9a83540ee0c45b144962c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StyleContext.java +++ b/src/java.desktop/share/classes/javax/swing/text/StyleContext.java @@ -579,7 +579,7 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon * Context-specific handling of writing out attributes * @param out the output stream * @param a the attribute set - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ public void writeAttributes(ObjectOutputStream out, AttributeSet a) throws IOException { @@ -591,9 +591,9 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon * @param in the object stream to read the attribute data from. * @param a the attribute set to place the attribute * definitions in. - * @exception ClassNotFoundException passed upward if encountered + * @throws ClassNotFoundException passed upward if encountered * when reading the object stream. - * @exception IOException passed upward if encountered when + * @throws IOException passed upward if encountered when * reading the object stream. */ public void readAttributes(ObjectInputStream in, @@ -613,7 +613,7 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon * * @param out the output stream * @param a the attribute set - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a) throws IOException { @@ -660,9 +660,9 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon * @param in the object stream to read the attribute data from. * @param a the attribute set to place the attribute * definitions in. - * @exception ClassNotFoundException passed upward if encountered + * @throws ClassNotFoundException passed upward if encountered * when reading the object stream. - * @exception IOException passed upward if encountered when + * @throws IOException passed upward if encountered when * reading the object stream. */ public static void readAttributeSet(ObjectInputStream in, @@ -1077,7 +1077,7 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon * Returns the next element of this enumeration. * * @return the next element of this enumeration. - * @exception NoSuchElementException if no more elements exist. + * @throws NoSuchElementException if no more elements exist. * @since 1.0 */ public Object nextElement() { diff --git a/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java index 00ad982cbf45d939dd91fc37146f1018b8eee6b5..a4984efce6c0f609443a661a1c1ed82923def864 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java @@ -411,7 +411,7 @@ public class StyledEditorKit extends DefaultEditorKit { * * @param e the editor * @return the document - * @exception IllegalArgumentException for the wrong document type + * @throws IllegalArgumentException for the wrong document type */ protected final StyledDocument getStyledDocument(JEditorPane e) { Document d = e.getDocument(); @@ -426,7 +426,7 @@ public class StyledEditorKit extends DefaultEditorKit { * * @param e the editor pane * @return the kit - * @exception IllegalArgumentException for the wrong document type + * @throws IllegalArgumentException for the wrong document type */ protected final StyledEditorKit getStyledEditorKit(JEditorPane e) { EditorKit k = e.getEditorKit(); diff --git a/src/java.desktop/share/classes/javax/swing/text/TableView.java b/src/java.desktop/share/classes/javax/swing/text/TableView.java index bd1c677ffaec7d48d74ba615dc23f52490775e0f..d18bd5a93db49bd3db24cb1b0e69c4da2836edd5 100644 --- a/src/java.desktop/share/classes/javax/swing/text/TableView.java +++ b/src/java.desktop/share/classes/javax/swing/text/TableView.java @@ -805,7 +805,7 @@ public abstract class TableView extends BoxView { * * @param axis may be either View.X_AXIS or View.Y_AXIS * @return the resize weight - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public int getResizeWeight(int axis) { return 1; diff --git a/src/java.desktop/share/classes/javax/swing/text/Utilities.java b/src/java.desktop/share/classes/javax/swing/text/Utilities.java index ae93b5a40b5f01dc1a79ec277bcf0cfbfc9a27c8..62f323f076aa5ac23eb7481f07935b43e940bb96 100644 --- a/src/java.desktop/share/classes/javax/swing/text/Utilities.java +++ b/src/java.desktop/share/classes/javax/swing/text/Utilities.java @@ -683,7 +683,7 @@ public class Utilities { * @param offs the offset in the document >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ @SuppressWarnings("deprecation") public static final int getRowStart(JTextComponent c, int offs) throws BadLocationException { @@ -714,7 +714,7 @@ public class Utilities { * @param offs the offset in the document >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ @SuppressWarnings("deprecation") public static final int getRowEnd(JTextComponent c, int offs) throws BadLocationException { @@ -747,7 +747,7 @@ public class Utilities { * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range * * @deprecated replaced by * {@link #getPositionAbove(JTextComponent, int, float)} @@ -802,7 +802,7 @@ public class Utilities { * @param x the X coordinate {@code >= 0} * @return the position {@code >= 0} if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range * * @since 9 */ @@ -822,7 +822,7 @@ public class Utilities { * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range * * @deprecated replaced by * {@link #getPositionBelow(JTextComponent, int, float)} @@ -878,7 +878,7 @@ public class Utilities { * @param x the X coordinate {@code >= 0} * @return the position {@code >= 0} if the request can be computed, otherwise * a value of -1 will be returned. - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range * * @since 9 */ @@ -894,7 +894,7 @@ public class Utilities { * @param c the editor * @param offs the offset in the document >= 0 * @return the location in the model of the word start >= 0 - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ public static final int getWordStart(JTextComponent c, int offs) throws BadLocationException { Document doc = c.getDocument(); @@ -928,7 +928,7 @@ public class Utilities { * @param c the editor * @param offs the offset in the document >= 0 * @return the location in the model of the word end >= 0 - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ public static final int getWordEnd(JTextComponent c, int offs) throws BadLocationException { Document doc = c.getDocument(); @@ -961,7 +961,7 @@ public class Utilities { * @param c the editor * @param offs the offset in the document >= 0 * @return the location in the model of the word start >= 0 - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ public static final int getNextWord(JTextComponent c, int offs) throws BadLocationException { int nextWord; @@ -1039,7 +1039,7 @@ public class Utilities { * @param c the editor * @param offs the offset in the document >= 0 * @return the location in the model of the word start >= 0 - * @exception BadLocationException if the offset is out of range + * @throws BadLocationException if the offset is out of range */ public static final int getPreviousWord(JTextComponent c, int offs) throws BadLocationException { int prevWord; @@ -1271,8 +1271,8 @@ public class Utilities { * @param biasRet an array contain the bias that was checked * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException - * @exception IllegalArgumentException if direction is invalid + * @throws BadLocationException + * @throws IllegalArgumentException if direction is invalid */ static int getNextVisualPositionFrom(View v, int pos, Position.Bias b, Shape alloc, int direction, diff --git a/src/java.desktop/share/classes/javax/swing/text/View.java b/src/java.desktop/share/classes/javax/swing/text/View.java index a3ad927e3a8e5185d471f53677be8715f96a1e43..eb10efb0e83fb36f933dd46c20a72b74da601604 100644 --- a/src/java.desktop/share/classes/javax/swing/text/View.java +++ b/src/java.desktop/share/classes/javax/swing/text/View.java @@ -495,9 +495,9 @@ public abstract class View implements SwingConstants { * @param biasRet the returned bias * @return the location within the model that best represents the next * location visual position - * @exception BadLocationException the given position is not a valid + * @throws BadLocationException the given position is not a valid * position within the document - * @exception IllegalArgumentException if direction + * @throws IllegalArgumentException if direction * doesn't have one of the legal values above */ @SuppressWarnings("deprecation") @@ -585,9 +585,9 @@ public abstract class View implements SwingConstants { * * @return the bounding box, in view coordinate space, * of the character at the specified position - * @exception BadLocationException if the specified position does + * @throws BadLocationException if the specified position does * not represent a valid location in the associated document - * @exception IllegalArgumentException if b is not one of the + * @throws IllegalArgumentException if b is not one of the * legal Position.Bias values listed above * @see View#viewToModel */ @@ -615,9 +615,9 @@ public abstract class View implements SwingConstants { * @param a the area of the view, which encompasses the requested region * @return the bounding box which is a union of the region specified * by the first and last character positions - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document - * @exception IllegalArgumentException if b0 or + * @throws IllegalArgumentException if b0 or * b1 are not one of the * legal Position.Bias values listed above * @see View#viewToModel @@ -1337,7 +1337,7 @@ public abstract class View implements SwingConstants { * @param pos the position to convert >= 0 * @param a the allocated region in which to render * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does + * @throws BadLocationException if the given position does * not represent a valid location in the associated document * @see View#modelToView * @deprecated diff --git a/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java b/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java index b229fa69f9f88c1ddeccf9a9508a4b3cc79104ca..d3587c8b40b4bd56b40dc98cb399ac8f6d9e8a50 100644 --- a/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java +++ b/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java @@ -207,7 +207,7 @@ public class WrappedPlainView extends BoxView implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= p0 * @return the X location of the end of the range >= 0 - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @deprecated replaced by * {@link #drawUnselectedText(Graphics2D, float, float, int, int)} @@ -252,7 +252,7 @@ public class WrappedPlainView extends BoxView implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= p0 * @return the X location of the end of the range >= 0 - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @since 9 */ @@ -272,7 +272,7 @@ public class WrappedPlainView extends BoxView implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= p0 * @return the location of the end of the range. - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @deprecated replaced by * {@link #drawSelectedText(Graphics2D, float, float, int, int)} @@ -320,7 +320,7 @@ public class WrappedPlainView extends BoxView implements TabExpander { * @param p0 the beginning position in the model >= 0 * @param p1 the ending position in the model >= p0 * @return the location of the end of the range. - * @exception BadLocationException if the range is invalid + * @throws BadLocationException if the range is invalid * * @since 9 */ @@ -748,7 +748,7 @@ public class WrappedPlainView extends BoxView implements TabExpander { * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position is returned - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/ZoneView.java b/src/java.desktop/share/classes/javax/swing/text/ZoneView.java index 1deb927fb6e5fdc558c75710c8a6caef5cff7598..595eafc336bd9ec71cb7df0da0f6c118665a4d2b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/ZoneView.java +++ b/src/java.desktop/share/classes/javax/swing/text/ZoneView.java @@ -134,7 +134,7 @@ public class ZoneView extends BoxView { * * @param mzl the desired maximum number of zones * to be actively loaded, must be greater than 0 - * @exception IllegalArgumentException if mzl is < 1 + * @throws IllegalArgumentException if mzl is < 1 */ public void setMaxZonesLoaded(int mzl) { if (mzl < 1) { @@ -579,7 +579,7 @@ public class ZoneView extends BoxView { * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java index 12cd5a74a721795e3814091d2bdd31621d3491e9..77623a541e00d3aa059c2d2483ae9765d1e95dbf 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java @@ -384,7 +384,7 @@ class AccessibleHTML implements 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/javax/swing/text/html/BlockView.java b/src/java.desktop/share/classes/javax/swing/text/html/BlockView.java index 524a57d93c1ee47ddfd762d46b56effeff90459f..dc2a5e22477128b73508d6f9de47acbfc1b9cd07 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/BlockView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/BlockView.java @@ -300,7 +300,7 @@ public class BlockView extends BoxView { * * @param axis may be either X_AXIS or Y_AXIS * @return the weight - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public int getResizeWeight(int axis) { switch (axis) { @@ -356,7 +356,7 @@ public class BlockView extends BoxView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getPreferredSpan(int axis) { return super.getPreferredSpan(axis); @@ -372,7 +372,7 @@ public class BlockView extends BoxView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMinimumSpan(int axis) { return super.getMinimumSpan(axis); @@ -388,7 +388,7 @@ public class BlockView extends BoxView { * typically the view is told to render into the span * that is returned, although there is no guarantee; * the parent may choose to resize or break the view - * @exception IllegalArgumentException for an invalid axis type + * @throws IllegalArgumentException for an invalid axis type */ public float getMaximumSpan(int axis) { return super.getMaximumSpan(axis); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/FormView.java b/src/java.desktop/share/classes/javax/swing/text/html/FormView.java index 467651a9d98d2071c3aa6c5165eb92d3e45f800d..b0855832a1d3924b9299b1afaec5c1fc8b4ac570 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/FormView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/FormView.java @@ -380,7 +380,7 @@ public class FormView extends ComponentView implements ActionListener { * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public float getMaximumSpan(int axis) { switch (axis) { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java b/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java index 885f0b7f2c9d63411d4b0210a5d22c957531db11..29a7fce803df876197d20c091f96452bc1163b9d 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java @@ -245,7 +245,7 @@ class HRuleView extends View { * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java index 46d84e3cadcc31da718c032f2d172a431dc3501a..f4bbb772e78c70d50035a5b751e156abae21226a 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java @@ -427,7 +427,7 @@ public class HTMLDocument extends DefaultStyledDocument { * * @param offset the starting offset * @param data the element data - * @exception BadLocationException if the given position does not + * @throws BadLocationException if the given position does not * represent a valid location in the associated document. */ protected void insert(int offset, ElementSpec[] data) throws BadLocationException { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index 8d78819b0e8d4e169bf6894804976c50fcf784e2..a5c1067f03f1f4fb25918668b6a2302d5bb77fb7 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -298,10 +298,10 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { * @param doc the destination for the insertion * @param pos the location in the document to place the * content - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document - * @exception RuntimeException (will eventually be a BadLocationException) + * @throws RuntimeException (will eventually be a BadLocationException) * if pos is invalid */ public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { @@ -337,7 +337,7 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { * * @throws BadLocationException if {@code offset} is invalid * @throws IOException on I/O error - * @exception RuntimeException (will eventually be a BadLocationException) + * @throws RuntimeException (will eventually be a BadLocationException) * if pos is invalid */ public void insertHTML(HTMLDocument doc, int offset, String html, @@ -367,8 +367,8 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { * @param pos the location in the document to fetch the * content * @param len the amount to write out - * @exception IOException on any I/O error - * @exception BadLocationException if {@code pos} represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if {@code pos} represents an invalid * location within the document */ public void write(Writer out, Document doc, int pos, int len) diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java index c11214d71e3bce696dcef6900888ad0eabf6ce92..270e46153098e93549e69cb4006b2dd97c5a759c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java @@ -125,8 +125,8 @@ public class HTMLWriter extends AbstractWriter { * Element tree and controls the writing out of * all the tags and its attributes. * - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. * */ @@ -248,7 +248,7 @@ public class HTMLWriter extends AbstractWriter { * HTML.Attribute.ENDTAG. * * @param attr an AttributeSet - * @exception IOException on any I/O error + * @throws IOException on any I/O error * */ protected void writeAttributes(AttributeSet attr) throws IOException { @@ -273,8 +273,8 @@ public class HTMLWriter extends AbstractWriter { * corresponding end tag). * * @param elem an Element - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void emptyTag(Element elem) throws BadLocationException, IOException { @@ -451,8 +451,8 @@ public class HTMLWriter extends AbstractWriter { * element. * * @param attr an AttributeSet - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void textAreaContent(AttributeSet attr) throws BadLocationException, IOException { @@ -485,8 +485,8 @@ public class HTMLWriter extends AbstractWriter { * out. * * @param elem an Element - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void text(Element elem) throws BadLocationException, IOException { @@ -523,7 +523,7 @@ public class HTMLWriter extends AbstractWriter { * Writes out the content of the SELECT form element. * * @param attr the AttributeSet associated with the form element - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void selectContent(AttributeSet attr) throws IOException { Object model = attr.getAttribute(StyleConstants.ModelAttribute); @@ -552,7 +552,7 @@ public class HTMLWriter extends AbstractWriter { /** * Writes out the content of the Option form element. * @param option an Option - * @exception IOException on any I/O error + * @throws IOException on any I/O error * */ protected void writeOption(Option option) throws IOException { @@ -580,7 +580,7 @@ public class HTMLWriter extends AbstractWriter { * Writes out an end tag for the element. * * @param elem an Element - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void endTag(Element elem) throws IOException { if (synthesizedElement(elem)) { @@ -615,8 +615,8 @@ public class HTMLWriter extends AbstractWriter { * Writes out comments. * * @param elem an Element - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void comment(Element elem) throws BadLocationException, IOException { @@ -637,8 +637,8 @@ public class HTMLWriter extends AbstractWriter { * Writes out comment string. * * @param string the comment - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ void writeComment(String string) throws IOException { @@ -712,7 +712,7 @@ public class HTMLWriter extends AbstractWriter { * written out. * * @param attr a set of attributes - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeEmbeddedTags(AttributeSet attr) throws IOException { @@ -767,7 +767,7 @@ public class HTMLWriter extends AbstractWriter { * end tag is written out. * * @param attr a set of attributes - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void closeOutUnwantedEmbeddedTags(AttributeSet attr) throws IOException { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java b/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java index 6f0a7cbdff41431d09ea34caa4183ed216fb074a..7d2583509c16a4be9fd0c2001c70e67c3ef43af3 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java @@ -557,7 +557,7 @@ public class ImageView extends View { * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position - * @exception BadLocationException if the given position does not represent a + * @throws BadLocationException if the given position does not represent a * valid location in the associated document * @see View#modelToView */ diff --git a/src/java.desktop/share/classes/javax/swing/text/html/MinimalHTMLWriter.java b/src/java.desktop/share/classes/javax/swing/text/html/MinimalHTMLWriter.java index caa8dd07051938e66e38691ca7fd785fae5d788e..712cb350ee95d5e3036c3bf5963085c2078740e0 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/MinimalHTMLWriter.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/MinimalHTMLWriter.java @@ -128,8 +128,8 @@ public class MinimalHTMLWriter extends AbstractWriter { * Generates HTML output * from a StyledDocument. * - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. * */ @@ -152,7 +152,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * The attribute name and value are separated by a colon. * Each pair is separated by a semicolon. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeAttributes(AttributeSet attr) throws IOException { Enumeration attributeNames = attr.getAttributeNames(); @@ -178,7 +178,7 @@ public class MinimalHTMLWriter extends AbstractWriter { /** * Writes out text. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void text(Element elem) throws IOException, BadLocationException { String contentStr = getText(elem); @@ -196,7 +196,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * indented. Also increments the indent level. * * @param tag a start tag - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeStartTag(String tag) throws IOException { indent(); @@ -211,7 +211,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * indented. Also decrements the indent level. * * @param endTag an end tag - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeEndTag(String endTag) throws IOException { decrIndent(); @@ -230,7 +230,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * document is viewable in applications/browsers * that do not support the tag. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeHeader() throws IOException { writeStartTag(""); @@ -248,7 +248,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * Writes out all the named styles as the * content of the <style> tag. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeStyles() throws IOException { /* @@ -338,7 +338,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * that all other tags that have been opened are * appropriately closed off. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeEndParagraph() throws IOException { writeEndMask(fontMask); @@ -359,7 +359,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * style. * * @param elem an element - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeStartParagraph(Element elem) throws IOException { AttributeSet attr = elem.getAttributes(); @@ -377,7 +377,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * elements. * * @param elem an element - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeLeaf(Element elem) throws IOException { indent(); @@ -434,8 +434,8 @@ public class MinimalHTMLWriter extends AbstractWriter { * * @param elem an element * @param needsIndenting indention will be added if {@code needsIndenting} is {@code true} - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ protected void writeContent(Element elem, boolean needsIndenting) @@ -457,7 +457,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * text based on its attribute settings. * * @param attr a set of attributes - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeHTMLTags(AttributeSet attr) throws IOException { @@ -522,7 +522,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * Writes out start tags <u>, <i>, and <b> based on * the mask settings. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ private void writeStartMask(int mask) throws IOException { if (mask != 0) { @@ -542,7 +542,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * Writes out end tags for <u>, <i>, and <b> based on * the mask settings. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ private void writeEndMask(int mask) throws IOException { if (mask != 0) { @@ -569,7 +569,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * attributes just like inline styles. * * @param attr a set of attributes - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void writeNonHTMLAttributes(AttributeSet attr) throws IOException { @@ -636,7 +636,7 @@ public class MinimalHTMLWriter extends AbstractWriter { *

    * Writes out an end tag for the <font> tag. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void endFontTag() throws IOException { write(NEWLINE); @@ -655,7 +655,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * new start tag. * * @param style a font style - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ protected void startFontTag(String style) throws IOException { boolean callIndent = false; @@ -676,7 +676,7 @@ public class MinimalHTMLWriter extends AbstractWriter { * any enclosing font tag before writing out a * new start tag. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ private void startSpanTag(String style) throws IOException { boolean callIndent = false; @@ -693,7 +693,7 @@ public class MinimalHTMLWriter extends AbstractWriter { /** * Writes out an end tag for the <span> tag. * - * @exception IOException on any I/O error + * @throws IOException on any I/O error */ private void endSpanTag() throws IOException { write(NEWLINE); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/OptionListModel.java b/src/java.desktop/share/classes/javax/swing/text/html/OptionListModel.java index 2b84b54b3e162ddb924c985c7d2d63f5fb7b53d8..c7f0ff34a9bd1ff62f6b33197a7e26b20a04cf5c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/OptionListModel.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/OptionListModel.java @@ -464,7 +464,7 @@ class OptionListModel extends DefaultListModel implements ListSelectionMod * listenerLists are not duplicated. * * @return a clone of the receiver - * @exception CloneNotSupportedException if the receiver does not + * @throws CloneNotSupportedException if the receiver does not * both (a) implement the Cloneable interface * and (b) define a clone method */ diff --git a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java index 9ce35f47ee9eb420129ac6aef21a54da87209670..35002f9fff27e7887fa672a2bdfd8bc3b89bb9e4 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java @@ -1886,7 +1886,7 @@ public class StyleSheet extends StyleContext { * used to get the AttributeSet, and may be used to * resolve percentage arguments. * @return the inset needed for the margin, border and padding. - * @exception IllegalArgumentException for an invalid direction + * @throws IllegalArgumentException for an invalid direction */ public float getInset(int side, View v) { AttributeSet a = v.getAttributes(); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/TableView.java b/src/java.desktop/share/classes/javax/swing/text/html/TableView.java index c088bf0eb9a773ed0b0a280d39402dc6d95da1db..11b383acd3187ed587cf97eea3a1351d8ddb6e4c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/TableView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/TableView.java @@ -1611,7 +1611,7 @@ import javax.swing.text.*; * * @param axis may be either View.X_AXIS or View.Y_AXIS * @return the resize weight - * @exception IllegalArgumentException for an invalid axis + * @throws IllegalArgumentException for an invalid axis */ public int getResizeWeight(int axis) { return 1; diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFEditorKit.java index 794c2cfee40b3b4dea5bac1ff444f6c6d76ff0bf..f841d9119f50924268f966eaf953e5243b90db1f 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFEditorKit.java @@ -70,8 +70,8 @@ public class RTFEditorKit extends StyledEditorKit { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void read(InputStream in, Document doc, int pos) throws IOException, BadLocationException { @@ -97,8 +97,8 @@ public class RTFEditorKit extends StyledEditorKit { * @param pos The location in the document to fetch the * content. * @param len The amount to write out. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void write(OutputStream out, Document doc, int pos, int len) @@ -117,8 +117,8 @@ public class RTFEditorKit extends StyledEditorKit { * @param doc The destination for the insertion. * @param pos The location in the document to place the * content. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void read(Reader in, Document doc, int pos) @@ -143,8 +143,8 @@ public class RTFEditorKit extends StyledEditorKit { * @param pos The location in the document to fetch the * content. * @param len The amount to write out. - * @exception IOException on any I/O error - * @exception BadLocationException if pos represents an invalid + * @throws IOException on any I/O error + * @throws BadLocationException if pos represents an invalid * location within the document. */ public void write(Writer out, Document doc, int pos, int len) diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java index 7735895502ecce78574ffbbf314c928975b9ec26..11efb12e7a288791f7b721e2c31b5f33319fdb5f 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java @@ -174,12 +174,12 @@ public class DefaultMutableTreeNode implements Cloneable, * @param newChild the MutableTreeNode to insert under this node * @param childIndex the index in this node's child array * where this node is to be inserted - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * childIndex is out of bounds - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * newChild is null or is an * ancestor of this node - * @exception IllegalStateException if this node does not allow + * @throws IllegalStateException if this node does not allow * children * @see #isNodeDescendant */ @@ -211,7 +211,7 @@ public class DefaultMutableTreeNode implements Cloneable, * * @param childIndex the index in this node's child array * of the child to remove - * @exception ArrayIndexOutOfBoundsException if + * @throws ArrayIndexOutOfBoundsException if * childIndex is out of bounds */ public void remove(int childIndex) { @@ -247,7 +247,7 @@ public class DefaultMutableTreeNode implements Cloneable, * Returns the child at the specified index in this node's child array. * * @param index an index into this node's child array - * @exception ArrayIndexOutOfBoundsException if index + * @throws ArrayIndexOutOfBoundsException if index * is out of bounds * @return the TreeNode in this node's child array at the specified index */ @@ -278,7 +278,7 @@ public class DefaultMutableTreeNode implements Cloneable, * where n is the number of children. * * @param aChild the TreeNode to search for among this node's children - * @exception IllegalArgumentException if aChild + * @throws IllegalArgumentException if aChild * is null * @return an int giving the index of the node in this node's child * array, or -1 if the specified node is a not @@ -382,7 +382,7 @@ public class DefaultMutableTreeNode implements Cloneable, * null parent. * * @param aChild a child of this node to remove - * @exception IllegalArgumentException if aChild + * @throws IllegalArgumentException if aChild * is null or is not a child of this node */ public void remove(MutableTreeNode aChild) { @@ -412,9 +412,9 @@ public class DefaultMutableTreeNode implements Cloneable, * * @see #insert * @param newChild node to add as a child of this node - * @exception IllegalArgumentException if newChild + * @throws IllegalArgumentException if newChild * is null - * @exception IllegalStateException if this node does not allow + * @throws IllegalStateException if this node does not allow * children */ public void add(MutableTreeNode newChild) { @@ -846,7 +846,7 @@ public class DefaultMutableTreeNode implements Cloneable, * @param ancestor the node to start enumeration from * @see #isNodeAncestor * @see #isNodeDescendant - * @exception IllegalArgumentException if ancestor is + * @throws IllegalArgumentException if ancestor is * not an ancestor of this node * @return an enumeration for following the path from an ancestor of * this node to this one @@ -890,7 +890,7 @@ public class DefaultMutableTreeNode implements Cloneable, * throws NoSuchElementException. * * @return the first child of this node - * @exception NoSuchElementException if this node has no children + * @throws NoSuchElementException if this node has no children */ public TreeNode getFirstChild() { if (getChildCount() == 0) { @@ -905,7 +905,7 @@ public class DefaultMutableTreeNode implements Cloneable, * throws NoSuchElementException. * * @return the last child of this node - * @exception NoSuchElementException if this node has no children + * @throws NoSuchElementException if this node has no children */ public TreeNode getLastChild() { if (getChildCount() == 0) { @@ -925,7 +925,7 @@ public class DefaultMutableTreeNode implements Cloneable, * * @param aChild the child node to look for next child after it * @see #children - * @exception IllegalArgumentException if aChild is + * @throws IllegalArgumentException if aChild is * null or is not a child of this node * @return the child of this node that immediately follows * aChild @@ -957,7 +957,7 @@ public class DefaultMutableTreeNode implements Cloneable, * and is O(n) where n is the number of children. * * @param aChild the child node to look for previous child before it - * @exception IllegalArgumentException if aChild is null + * @throws IllegalArgumentException if aChild is null * or is not a child of this node * @return the child of this node that immediately precedes * aChild diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java index 4cdec3f6b381895d6c1bf98e8c489a1e43933ccf..511cde568c0929e9b189bf4ea4a850a6ee7f6fb3 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java @@ -672,7 +672,7 @@ public class DefaultTreeModel implements Serializable, TreeModel { * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java index e1bdc4fc94b3952bdf3856f43dc80d3979e1361c..ff7ed27302dcbbd9a5841e09c028fbe68e9e6cc0 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java @@ -679,7 +679,7 @@ public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeS * FooListeners on this component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @throws ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * @@ -1187,7 +1187,7 @@ public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeS * This method does not duplicate * selection listeners and property listeners. * - * @exception CloneNotSupportedException never thrown by instances of + * @throws CloneNotSupportedException never thrown by instances of * this class */ public Object clone() throws CloneNotSupportedException { diff --git a/src/java.desktop/share/classes/javax/swing/undo/AbstractUndoableEdit.java b/src/java.desktop/share/classes/javax/swing/undo/AbstractUndoableEdit.java index 7184557d1e77afb39045042080962bba6a1c6e47..94f5eb69a74ad19bc0f1fb3d22128e7005013c39 100644 --- a/src/java.desktop/share/classes/javax/swing/undo/AbstractUndoableEdit.java +++ b/src/java.desktop/share/classes/javax/swing/undo/AbstractUndoableEdit.java @@ -102,7 +102,7 @@ public class AbstractUndoableEdit implements UndoableEdit, Serializable { * operation represented by this edit. Override should begin with * a call to super. * - * @exception CannotUndoException if canUndo + * @throws CannotUndoException if canUndo * returns false * @see #canUndo */ @@ -134,7 +134,7 @@ public class AbstractUndoableEdit implements UndoableEdit, Serializable { * Subclasses should override to redo the operation represented by * this edit. Override should begin with a call to super. * - * @exception CannotRedoException if canRedo + * @throws CannotRedoException if canRedo * returns false * @see #canRedo */ diff --git a/src/java.desktop/share/classes/sun/awt/AppContext.java b/src/java.desktop/share/classes/sun/awt/AppContext.java index 6ed0b2b325efc7c3a95c893c67f9d18cc99f5bb9..741b52d8bae4a71de7106c392f9e239c2e4702d4 100644 --- a/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -391,7 +391,7 @@ public final class AppContext { * This method must be called from a Thread which is not contained * within this AppContext. * - * @exception IllegalThreadStateException if the current thread is + * @throws IllegalThreadStateException if the current thread is * contained within this AppContext * @since 1.2 */ @@ -660,7 +660,7 @@ public final class AppContext { * @param value the value. * @return the previous value of the specified key in this * AppContext, or {@code null} if it did not have one. - * @exception NullPointerException if the key or value is + * @throws NullPointerException if the key or value is * {@code null}. * @see #get(Object) * @since 1.2 diff --git a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java b/src/java.desktop/share/classes/sun/awt/FontConfiguration.java index e2e7ab3e5ae1bf488d9728a6c05c7e35b7e40e60..45035042992ea1dbd942a520feba3011beb59138 100644 --- a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java +++ b/src/java.desktop/share/classes/sun/awt/FontConfiguration.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 @@ -960,7 +960,9 @@ public abstract class FontConfiguration { return fc.newEncoder(); } - if (!charsetName.startsWith("sun.awt.") && !charsetName.equals("default")) { + if (!charsetName.startsWith("sun.awt.") && + !charsetName.equals("default") && + !charsetName.startsWith("sun.font.")) { fc = Charset.forName(charsetName); } else { @SuppressWarnings("removal") diff --git a/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/src/java.desktop/share/classes/sun/awt/SunToolkit.java index 380a5e4db017e29a66f329891bc075786e04dfa4..1e144c373e4d18b7183d5519d2b54e690dc26012 100644 --- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -1181,7 +1181,7 @@ public abstract class SunToolkit extends Toolkit variant = AccessController.doPrivileged( new GetPropertyAction("user.variant", "")); } - startupLocale = new Locale(language, country, variant); + startupLocale = Locale.of(language, country, variant); } return startupLocale; } diff --git a/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java b/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java index eb8f6368c20496dfa4969080c3b5a1f83cd78f72..5b32879b59814452c70edceb20577e33679b8f0b 100644 --- a/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java +++ b/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.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 @@ -375,7 +375,7 @@ class ExecutableInputMethodManager extends InputMethodManager variant = localeString.substring(postIndex + 1); } } - Locale locale = new Locale(language, country, variant); + Locale locale = Locale.of(language, country, variant); locator = locator.deriveLocator(locale); } @@ -550,8 +550,8 @@ class ExecutableInputMethodManager extends InputMethodManager if (preferredLocale.equals(Locale.KOREA)) { preferredLocale = Locale.KOREAN; } - if (preferredLocale.equals(new Locale("th", "TH"))) { - preferredLocale = new Locale("th"); + if (preferredLocale.equals(Locale.of("th", "TH"))) { + preferredLocale = Locale.of("th"); } // obtain node @@ -623,10 +623,10 @@ class ExecutableInputMethodManager extends InputMethodManager advertised = Locale.KOREAN; } } else if (locale.getLanguage().equals("th")) { - if (locator.isLocaleAvailable(new Locale("th", "TH"))) { - advertised = new Locale("th", "TH"); - } else if (locator.isLocaleAvailable(new Locale("th"))) { - advertised = new Locale("th"); + if (locator.isLocaleAvailable(Locale.of("th", "TH"))) { + advertised = Locale.of("th", "TH"); + } else if (locator.isLocaleAvailable(Locale.of("th"))) { + advertised = Locale.of("th"); } } diff --git a/src/java.desktop/share/classes/sun/awt/im/InputContext.java b/src/java.desktop/share/classes/sun/awt/im/InputContext.java index c35d17bfae3611114bb36694888975065cce65c2..237164a9d421cd5fee56d0c9895ce91a1e4fc365 100644 --- a/src/java.desktop/share/classes/sun/awt/im/InputContext.java +++ b/src/java.desktop/share/classes/sun/awt/im/InputContext.java @@ -133,7 +133,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#selectInputMethod - * @exception NullPointerException when the locale is null. + * @throws NullPointerException when the locale is null. */ public synchronized boolean selectInputMethod(Locale locale) { if (locale == null) { @@ -206,7 +206,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#reconvert * @since 1.3 - * @exception UnsupportedOperationException when input method is null + * @throws UnsupportedOperationException when input method is null */ public synchronized void reconvert() { InputMethod inputMethod = getInputMethod(); @@ -610,7 +610,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#removeNotify - * @exception NullPointerException when the component is null. + * @throws NullPointerException when the component is null. */ public synchronized void removeNotify(Component component) { if (component == null) { @@ -662,7 +662,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#dispose - * @exception IllegalStateException when the currentClientComponent is not null + * @throws IllegalStateException when the currentClientComponent is not null */ public synchronized void dispose() { if (currentClientComponent != null) { @@ -723,7 +723,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#setCompositionEnabled(boolean) - * @exception UnsupportedOperationException when input method is null + * @throws UnsupportedOperationException when input method is null */ public void setCompositionEnabled(boolean enable) { InputMethod inputMethod = getInputMethod(); @@ -736,7 +736,7 @@ public class InputContext extends java.awt.im.InputContext /** * @see java.awt.im.InputContext#isCompositionEnabled - * @exception UnsupportedOperationException when input method is null + * @throws UnsupportedOperationException when input method is null */ public boolean isCompositionEnabled() { InputMethod inputMethod = getInputMethod(); @@ -749,7 +749,7 @@ public class InputContext extends java.awt.im.InputContext /** * @return a string with information about the current input method. - * @exception UnsupportedOperationException when input method is null + * @throws UnsupportedOperationException when input method is null */ public String getInputMethodInfo() { InputMethod inputMethod = getInputMethod(); diff --git a/src/java.desktop/share/classes/sun/awt/im/InputMethodAdapter.java b/src/java.desktop/share/classes/sun/awt/im/InputMethodAdapter.java index dfc31799bfb037a5a798edb943545d4dea82298b..b70f5bbbf712e862125b6a2bb0ddd08c727e4086 100644 --- a/src/java.desktop/share/classes/sun/awt/im/InputMethodAdapter.java +++ b/src/java.desktop/share/classes/sun/awt/im/InputMethodAdapter.java @@ -93,7 +93,7 @@ public abstract class InputMethodAdapter implements InputMethod { /** * Starts reconvertion. An implementing host adapter has to override * this method if it can support reconvert(). - * @exception UnsupportedOperationException when the adapter does not override + * @throws UnsupportedOperationException when the adapter does not override * the method. */ public void reconvert() { diff --git a/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java b/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java index 882881f13b95833590389c36c1befa1984e8f255..0afae4060c07822ce2bcf3792e412fb9bf9cbd13 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java @@ -634,7 +634,7 @@ public class ByteBandedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public WritableRaster createWritableChild (int x, int y, @@ -689,7 +689,7 @@ public class ByteBandedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java b/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java index 6a92748330cb7d239e362b763b6449f3e9a379fd..3ec93b741e7cb65a87c9eac567226916aa96ed1e 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java @@ -759,7 +759,7 @@ public class ByteComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild(int x, int y, @@ -788,7 +788,7 @@ public class ByteComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java b/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java index 796f0835972ab4416059faf8b87ead8b87822530..f0dedd9775a3aeb20546fd60c67dfeb01959964b 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -1195,7 +1195,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild(int x, int y, @@ -1224,7 +1224,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java b/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java index d721eee57390d2898cfa2ac41412624f11c165d5..cadc390e6e9cba8879353e95ac4251d8a20ac3d9 100644 --- a/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java @@ -143,7 +143,7 @@ public class BytePackedRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. * - * @exception RasterFormatException if the parameters do not conform + * @throws RasterFormatException if the parameters do not conform * to requirements of this Raster type. */ public BytePackedRaster(SampleModel sampleModel, @@ -1258,7 +1258,7 @@ public class BytePackedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild(int x, int y, @@ -1286,7 +1286,7 @@ public class BytePackedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java b/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java index 3b110e77eca55b94814a1898434bcc1e29547403..e918a285aaaaeda2a0e170b5e4941af1c4c5742d 100644 --- a/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java @@ -535,7 +535,7 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public WritableRaster createWritableChild (int x, int y, @@ -589,7 +589,7 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subRaster. * @param y0 Translated Y origin of the subRaster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java b/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java index cb84024ae22d37f4994270cee70d347105acd1ad..b00b03011306b7efb69f8a40e88cb71c19c734f3 100644 --- a/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java @@ -447,7 +447,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public WritableRaster createWritableChild (int x, int y, @@ -501,7 +501,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param x0 Translated X origin of the subRaster. * @param y0 Translated Y origin of the subRaster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java b/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java index d84039265676354feda99d862b1adbd3e6c757cb..17d24e276860a166256d9a7669d516d98b62a6b5 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java @@ -633,7 +633,7 @@ public class ShortBandedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, @@ -689,7 +689,7 @@ public class ShortBandedRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java b/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java index 3e95f652d331ad1f5f3eb615e709afb4d7ef61c3..b24b664826fc26d7454420cbe7a3838f812827c9 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java @@ -693,7 +693,7 @@ public class ShortComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, @@ -722,7 +722,7 @@ public class ShortComponentRaster extends SunWritableRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java b/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java index d4926bb295eedd872e9e25f45b80441fc91da6a2..327adf9ac98a02ff7ffcdbe0c7e4ab38bc060bc9 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -666,7 +666,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent raster. */ public Raster createChild (int x, int y, @@ -695,7 +695,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param x0 Translated X origin of the subraster. * @param y0 Translated Y origin of the subraster. * @param bandList Array of band indices. - * @exception RasterFormatException + * @throws RasterFormatException * if the specified bounding box is outside of the parent Raster. */ public WritableRaster createWritableChild(int x, int y, diff --git a/src/java.desktop/share/classes/sun/awt/resources/awt_de.properties b/src/java.desktop/share/classes/sun/awt/resources/awt_de.properties index 471c4c2fc8b3d2c87c47345440b30e7e4de0c1bc..80e22e5c8cf40509355b4088dae81adb7348bb4d 100644 --- a/src/java.desktop/share/classes/sun/awt/resources/awt_de.properties +++ b/src/java.desktop/share/classes/sun/awt/resources/awt_de.properties @@ -201,8 +201,8 @@ AWT.HostInputMethodDisplayName=Systemeingabemethoden AWT.InputMethodLanguage.ja=Japanisch AWT.InputMethodLanguage.ko=Koreanisch AWT.InputMethodLanguage.zh=Chinesisch -AWT.InputMethodLanguage.zh_CN=Vereinfachtes Chinesisch -AWT.InputMethodLanguage.zh_TW=Traditionelles Chinesisch +AWT.InputMethodLanguage.zh_CN=Chinesisch (vereinfacht) +AWT.InputMethodLanguage.zh_TW=Chinesisch (traditionell) AWT.InputMethodCreationFailed={0} konnte nicht erstellt werden. Grund: {1} # Property to select between on-the-spot and below-the-spot diff --git a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java index 3aa91dcb6006f31bb0e7ed32719098c4b69407a8..1f95995a222ae3258d6038e296bd6114ebe5c15e 100644 --- a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java +++ b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java @@ -253,13 +253,12 @@ public abstract class ShellFolder extends File { /** * Return a shell folder from a file object - * @exception FileNotFoundException if file does not exist + * @throws FileNotFoundException if file does not exist */ public static ShellFolder getShellFolder(File file) throws FileNotFoundException { if (file instanceof ShellFolder) { return (ShellFolder)file; } - if (!Files.exists(Paths.get(file.getPath()), LinkOption.NOFOLLOW_LINKS)) { throw new FileNotFoundException(); } diff --git a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java index 98f93cc3ec7027fa9942a230d7889addeb9ea0df..202a55a8135bd55d46296aefb8127d180ab96d99 100644 --- a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java +++ b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java @@ -113,7 +113,7 @@ public class IdentityArrayList extends AbstractList * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list - * @exception IllegalArgumentException if the specified initial capacity + * @throws IllegalArgumentException if the specified initial capacity * is negative */ public IdentityArrayList(int initialCapacity) { diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 4f36498f6e2718fee47ee1b067a8a92612e81db0..3395e343e2e692c7ab399ca5339ecd9871a181ad 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.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 @@ -3466,7 +3466,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { String language = System.getProperty("user.language", "en"); String country = System.getProperty("user.country",""); String variant = System.getProperty("user.variant",""); - return new Locale(language, country, variant); + return Locale.of(language, country, variant); } }); } diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 193a8a38587ecc7c989956ea8a94b463d5c32408..5c681b454b9deae5bb39b5c29da942886dcc5277 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -409,7 +409,7 @@ public final class SunGraphics2D * drawback of the workaround is that the resulting * clip and device origin cannot be "enforced". * - * @exception IllegalStateException If the Graphics + * @throws IllegalStateException If the Graphics * to be constrained has a complex transform. */ @Override diff --git a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java index 61450e49553f7c788d39ebe30da208ac6cbeba84..01a24adfda43fe58bb3d2464a6a06a3d354e2046 100644 --- a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java @@ -418,7 +418,7 @@ public class PSPrinterJob extends RasterPrinterJob { * print job interactively. * @return false if the user cancels the dialog and * true otherwise. - * @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/sun/print/PrintJob2D.java b/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 9083bd3e26965be3ba66460049c4f645a5dc2b7b..7a238383ce859a4fdb586cb63c1003d030facf00 100644 --- a/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -966,7 +966,7 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { * @return PAGE_EXISTS if the page is rendered successfully * or NO_SUCH_PAGE if {@code pageIndex} specifies a * non-existent page. - * @exception java.awt.print.PrinterException + * @throws java.awt.print.PrinterException * thrown when the print job is terminated. */ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) diff --git a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 6ceeb48df85279161c11f8fb6327c4147a8059ef..ffdebb82d0ba221d3d039bbbfb2da2e15c90fd75 100644 --- a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -714,7 +714,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * is cancelled, or a new PageFormat object containing * the format indicated by the user if the dialog is * acknowledged - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -947,7 +947,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * * @param attributes to store changed properties. * @return false if the user cancels the dialog and true otherwise. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -1100,7 +1100,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * print job interactively. * @return false if the user cancels the dialog and * true otherwise. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -1183,7 +1183,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * for the number of pages as well as the PageFormat and * Printable for each page. * @param document The document to be printed. It may not be null. - * @exception NullPointerException the Pageable passed in was null. + * @throws NullPointerException the Pageable passed in was null. * @see PageFormat * @see Printable */ @@ -1477,7 +1477,7 @@ public abstract class RasterPrinterJob extends PrinterJob { /** * Prints a set of pages. - * @exception java.awt.print.PrinterException an error in the print system + * @throws java.awt.print.PrinterException an error in the print system * caused the job to be aborted * @see java.awt.print.Book * @see java.awt.print.Pageable diff --git a/make/data/dtdbuilder/HTMLlat1.sgml b/src/java.desktop/share/data/dtdbuilder/HTMLlat1.sgml similarity index 100% rename from make/data/dtdbuilder/HTMLlat1.sgml rename to src/java.desktop/share/data/dtdbuilder/HTMLlat1.sgml diff --git a/make/data/dtdbuilder/HTMLspecial.sgml b/src/java.desktop/share/data/dtdbuilder/HTMLspecial.sgml similarity index 100% rename from make/data/dtdbuilder/HTMLspecial.sgml rename to src/java.desktop/share/data/dtdbuilder/HTMLspecial.sgml diff --git a/make/data/dtdbuilder/HTMLsymbol.sgml b/src/java.desktop/share/data/dtdbuilder/HTMLsymbol.sgml similarity index 100% rename from make/data/dtdbuilder/HTMLsymbol.sgml rename to src/java.desktop/share/data/dtdbuilder/HTMLsymbol.sgml diff --git a/make/data/dtdbuilder/html32.dtd b/src/java.desktop/share/data/dtdbuilder/html32.dtd similarity index 100% rename from make/data/dtdbuilder/html32.dtd rename to src/java.desktop/share/data/dtdbuilder/html32.dtd diff --git a/make/data/dtdbuilder/public.map b/src/java.desktop/share/data/dtdbuilder/public.map similarity index 100% rename from make/data/dtdbuilder/public.map rename to src/java.desktop/share/data/dtdbuilder/public.map diff --git a/src/java.desktop/share/native/liblcms/LCMS.c b/src/java.desktop/share/native/liblcms/LCMS.c index 27c23c6d92f6f749173aa80115f5a44364d724e5..06a7eb261408bfd8505e3a27109438fda335741b 100644 --- a/src/java.desktop/share/native/liblcms/LCMS.c +++ b/src/java.desktop/share/native/liblcms/LCMS.c @@ -734,34 +734,43 @@ static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget, // now we have all tags moved to the new profile. // do some sanity checks: write it to a memory buffer and read again. + void* buf = NULL; if (cmsSaveProfileToMem(p, NULL, &pfSize)) { - void* buf = malloc(pfSize); + buf = malloc(pfSize); if (buf != NULL) { // load raw profile data into the buffer if (cmsSaveProfileToMem(p, buf, &pfSize)) { pfSanity = cmsOpenProfileFromMem(buf, pfSize); } - free(buf); } } + cmsCloseProfile(p); // No longer needed. + if (pfSanity == NULL) { // for some reason, we failed to save and read the updated profile // It likely indicates that the profile is not correct, so we report // a failure here. - cmsCloseProfile(p); - p = NULL; + free(buf); + return NULL; } else { // do final check whether we can read and handle the target tag. const void* pTag = cmsReadTag(pfSanity, sig); if (pTag == NULL) { // the tag can not be cooked - cmsCloseProfile(p); - p = NULL; + free(buf); + cmsCloseProfile(pfSanity); + return NULL; } + // The profile we used for sanity checking needs to be returned + // since the one we updated is raw - not cooked. + // Except we want to re-open it since the call to cmsReadTag() + // means we may not get back the same bytes as we set. + // Whilst this may change later anyway, we can at least prevent + // it from happening immediately. cmsCloseProfile(pfSanity); - pfSanity = NULL; + pfSanity = cmsOpenProfileFromMem(buf, pfSize); + free(buf); + return pfSanity; } - - return p; } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java b/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java index a7ab4f3e830745989d148005e629da74332f9100..7a23c806374b8eba66728815c7f9142270bc3dc8 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.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 @@ -524,13 +524,6 @@ static native String XSetLocaleModifiers(String modifier_list); static native void XChangeActivePointerGrab(long display, int mask, long cursor, long time); - /* - int (*XSynchronize(Display *display, Bool onoff))(); - display Specifies the connection to the X server. - onoff Specifies a Boolean value that indicates whether to enable or disable synchronization. - */ - static native int XSynchronize(long display, boolean onoff); - /** * Extracts an X event that can be processed in a secondary loop. * Should only be called on the toolkit thread. diff --git a/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java b/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java index e41a096f55f60d2f5ffe001621324ec9367f1842..0e398edef8575a020cbecf181f22986b7d082607 100644 --- a/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java +++ b/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java @@ -53,6 +53,7 @@ public class CUPSPrinter { private static native String getCupsServer(); private static native int getCupsPort(); private static native String getCupsDefaultPrinter(); + private static native String[] getCupsDefaultPrinters(); private static native boolean canConnect(String server, int port); private static native boolean initIDs(); // These functions need to be synchronized as @@ -77,6 +78,7 @@ public class CUPSPrinter { private static boolean libFound; private static String cupsServer = null; + private static String domainSocketPathname = null; private static int cupsPort = 0; static { @@ -96,6 +98,13 @@ public class CUPSPrinter { libFound = initIDs(); if (libFound) { cupsServer = getCupsServer(); + // Is this a local domain socket pathname? + if (cupsServer != null && cupsServer.startsWith("/")) { + if (isSandboxedApp()) { + domainSocketPathname = cupsServer; + } + cupsServer = "localhost"; + } cupsPort = getCupsPort(); } } @@ -381,6 +390,20 @@ public class CUPSPrinter { * Get list of all CUPS printers using IPP. */ static String[] getAllPrinters() { + + if (getDomainSocketPathname() != null) { + String[] printerNames = getCupsDefaultPrinters(); + if (printerNames != null && printerNames.length > 0) { + String[] printerURIs = new String[printerNames.length]; + for (int i=0; i< printerNames.length; i++) { + printerURIs[i] = String.format("ipp://%s:%d/printers/%s", + getServer(), getPort(), printerNames[i]); + } + return printerURIs; + } + return null; + } + try { URL url = new URL("http", getServer(), getPort(), ""); @@ -464,15 +487,39 @@ public class CUPSPrinter { return cupsPort; } + /** + * Returns CUPS domain socket pathname. + */ + private static String getDomainSocketPathname() { + return domainSocketPathname; + } + + @SuppressWarnings("removal") + private static boolean isSandboxedApp() { + if (PrintServiceLookupProvider.isMac()) { + return java.security.AccessController + .doPrivileged((java.security.PrivilegedAction) () -> + System.getenv("APP_SANDBOX_CONTAINER_ID") != null); + } + return false; + } + + /** * Detects if CUPS is running. */ public static boolean isCupsRunning() { IPPPrintService.debug_println(debugPrefix+"libFound "+libFound); if (libFound) { - IPPPrintService.debug_println(debugPrefix+"CUPS server "+getServer()+ - " port "+getPort()); - return canConnect(getServer(), getPort()); + String server = getDomainSocketPathname() != null + ? getDomainSocketPathname() + : getServer(); + IPPPrintService.debug_println(debugPrefix+"CUPS server "+server+ + " port "+getPort()+ + (getDomainSocketPathname() != null + ? " use domain socket pathname" + : "")); + return canConnect(server, getPort()); } else { return false; } diff --git a/make/data/x11wrappergen/sizes-32.txt b/src/java.desktop/unix/data/x11wrappergen/sizes-32.txt similarity index 100% rename from make/data/x11wrappergen/sizes-32.txt rename to src/java.desktop/unix/data/x11wrappergen/sizes-32.txt diff --git a/make/data/x11wrappergen/sizes-64.txt b/src/java.desktop/unix/data/x11wrappergen/sizes-64.txt similarity index 100% rename from make/data/x11wrappergen/sizes-64.txt rename to src/java.desktop/unix/data/x11wrappergen/sizes-64.txt diff --git a/make/data/x11wrappergen/xlibtypes.txt b/src/java.desktop/unix/data/x11wrappergen/xlibtypes.txt similarity index 100% rename from make/data/x11wrappergen/xlibtypes.txt rename to src/java.desktop/unix/data/x11wrappergen/xlibtypes.txt diff --git a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c index 62f57ffde5edec4a7b871e7ff6676f7e2ed28d3a..52677659ed3bed340c50370844ddbb1da299f4c8 100644 --- a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c +++ b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c @@ -172,12 +172,7 @@ Java_sun_print_CUPSPrinter_getCupsServer(JNIEnv *env, jstring cServer = NULL; const char* server = j2d_cupsServer(); if (server != NULL) { - // Is this a local domain socket? - if (strncmp(server, "/", 1) == 0) { - cServer = JNU_NewStringPlatform(env, "localhost"); - } else { - cServer = JNU_NewStringPlatform(env, server); - } + cServer = JNU_NewStringPlatform(env, server); } return cServer; } @@ -219,6 +214,57 @@ Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env, return cDefPrinter; } +/* + * Returns list of default local printers + */ +JNIEXPORT jobjectArray JNICALL +Java_sun_print_CUPSPrinter_getCupsDefaultPrinters(JNIEnv *env, + jobject printObj) +{ + cups_dest_t *dests; + int i, j, num_dests; + jstring utf_str; + jclass cls; + jobjectArray nameArray = NULL; + + cls = (*env)->FindClass(env, "java/lang/String"); + CHECK_NULL_RETURN(cls, NULL); + + num_dests = j2d_cupsGetDests(&dests); + + if (dests == NULL) { + return NULL; + } + + nameArray = (*env)->NewObjectArray(env, num_dests, cls, NULL); + if (nameArray == NULL) { + j2d_cupsFreeDests(num_dests, dests); + DPRINTF("CUPSfuncs::bad alloc new array\n", "") + return NULL; + } + + for (i = 0; i < num_dests; i++) { + utf_str = JNU_NewStringPlatform(env, dests[i].name); + if (utf_str == NULL) { + for (j = i - 1; j >= 0; j--) { + utf_str = (*env)->GetObjectArrayElement(env, nameArray, j); + (*env)->SetObjectArrayElement(env, nameArray, j, NULL); + (*env)->DeleteLocalRef(env, utf_str); + utf_str = NULL; + } + j2d_cupsFreeDests(num_dests, dests); + (*env)->DeleteLocalRef(env, nameArray); + DPRINTF("CUPSfuncs::bad alloc new string ->name\n", "") + return NULL; + } + (*env)->SetObjectArrayElement(env, nameArray, i, utf_str); + (*env)->DeleteLocalRef(env, utf_str); + } + + j2d_cupsFreeDests(num_dests, dests); + return nameArray; +} + /* * Checks if connection can be made to the server. * diff --git a/src/java.desktop/unix/native/common/awt/fontpath.c b/src/java.desktop/unix/native/common/awt/fontpath.c index c4b2fcb73c06138d00e7e9a355209ff16cd248cf..fd28f5c0ea6dc1d2fe33afffb7462e206da0c837 100644 --- a/src/java.desktop/unix/native/common/awt/fontpath.c +++ b/src/java.desktop/unix/native/common/awt/fontpath.c @@ -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 @@ -496,6 +496,7 @@ typedef FcResult (*FcPatternGetStringFuncType)(const FcPattern *p, FcChar8 ** s); typedef FcChar8* (*FcStrDirnameFuncType)(const FcChar8 *file); typedef void (*FcPatternDestroyFuncType)(FcPattern *p); +typedef void (*FcObjectSetDestroyFuncType)(FcObjectSet *os); typedef void (*FcFontSetDestroyFuncType)(FcFontSet *s); typedef FcPattern* (*FcNameParseFuncType)(const FcChar8 *name); typedef FcBool (*FcPatternAddStringFuncType)(FcPattern *p, @@ -542,6 +543,7 @@ static char **getFontConfigLocations() { FcPatternGetStringFuncType FcPatternGetString; FcStrDirnameFuncType FcStrDirname; FcPatternDestroyFuncType FcPatternDestroy; + FcObjectSetDestroyFuncType FcObjectSetDestroy; FcFontSetDestroyFuncType FcFontSetDestroy; FcConfig *fontconfig; @@ -571,6 +573,8 @@ static char **getFontConfigLocations() { (FcStrDirnameFuncType)dlsym(libfontconfig, "FcStrDirname"); FcPatternDestroy = (FcPatternDestroyFuncType)dlsym(libfontconfig, "FcPatternDestroy"); + FcObjectSetDestroy = + (FcObjectSetDestroyFuncType)dlsym(libfontconfig, "FcObjectSetDestroy"); FcFontSetDestroy = (FcFontSetDestroyFuncType)dlsym(libfontconfig, "FcFontSetDestroy"); @@ -580,6 +584,7 @@ static char **getFontConfigLocations() { FcFontList == NULL || FcStrDirname == NULL || FcPatternDestroy == NULL || + FcObjectSetDestroy == NULL || FcFontSetDestroy == NULL) { /* problem with the library: return. */ closeFontConfig(libfontconfig, JNI_FALSE); return NULL; @@ -636,6 +641,7 @@ static char **getFontConfigLocations() { cleanup: /* Free memory and close the ".so" */ + (*FcObjectSetDestroy)(objset); (*FcPatternDestroy)(pattern); closeFontConfig(libfontconfig, JNI_TRUE); return fontdirs; @@ -935,8 +941,10 @@ Java_sun_font_FontConfigManager_getFontConfig if (cacheDirs != NULL) { while ((cnt < max) && (cacheDir = (*FcStrListNext)(cacheDirs))) { jstr = (*env)->NewStringUTF(env, (const char*)cacheDir); - JNU_CHECK_EXCEPTION(env); - + if (IS_NULL(jstr)) { + (*FcStrListDone)(cacheDirs); + return; + } (*env)->SetObjectArrayElement(env, cacheDirArray, cnt++, jstr); (*env)->DeleteLocalRef(env, jstr); } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 815289b7c8f75fb30359ce2623c5150944f73284..6d7d3125b946fc1f347f3edbc9591cd3028289df 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -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 @@ -579,7 +579,8 @@ cleanup: XFree (pVI8sg); if (n1sg != 0) XFree (pVI1sg); - + if (nTrue != 0) + XFree (pVITrue); AWT_UNLOCK (); } diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c b/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c index 19173eb6052cb81c04629465f8789800e485d5f2..20f5f2b4fc719efc9cdea701ab7da528de468b90 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c @@ -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 @@ -825,7 +825,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_SetProperty */ if (!JNU_IsNull(env, jstr)) { #ifdef X_HAVE_UTF8_STRING - cname = (char *) (*env)->GetStringUTFChars(env, jstr, JNI_FALSE); + cname = (char *) (*env)->GetStringUTFChars(env, jstr, NULL); #else cname = (char *) JNU_GetStringPlatformChars(env, jstr, NULL); #endif @@ -2184,11 +2184,6 @@ Java_sun_awt_X11_XlibWrapper_copyLongArray(JNIEnv *env, } } -JNIEXPORT jint JNICALL -Java_sun_awt_X11_XlibWrapper_XSynchronize(JNIEnv *env, jclass clazz, jlong display, jboolean onoff) -{ - return (jint) XSynchronize((Display*)jlong_to_ptr(display), (onoff == JNI_TRUE ? True : False)); -} JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XShapeQueryExtension diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index d28509271205a85709ecddc0dd8789b31cdafc67..4d65e2700ab2e071cc5a50eb90204ecbf793d815 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -258,7 +258,7 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager { if (!done && sd instanceof D3DWindowSurfaceData) { D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd; - if (!d3dw.isSurfaceLost() || validate(d3dw)) { + if (!d3dw.isSurfaceLost() || validate(d3dw, false)) { trackScreenSurface(d3dw); return new SunGraphics2D(sd, fgColor, bgColor, font); } @@ -452,7 +452,7 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager } finally { rq.unlock(); } - } else if (!validate(sd)) { + } else if (!validate(sd, true)) { // it is possible that the validation may never // succeed, we need to detect this and replace // the d3dw surface with gdi; the replacement of @@ -474,7 +474,7 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager * @return true if surface wasn't lost or if restoration was successful, * false otherwise */ - private boolean validate(D3DWindowSurfaceData sd) { + private boolean validate(D3DWindowSurfaceData sd, boolean postEvent) { if (sd.isSurfaceLost()) { try { sd.restoreSurface(); @@ -491,7 +491,9 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager sd.markClean(); // since the surface was successfully restored we need to // repaint whole window to repopulate the back-buffer - repaintPeerTarget(sd.getPeer()); + if (postEvent) { + repaintPeerTarget(sd.getPeer()); + } } catch (InvalidPipeException ipe) { return false; } diff --git a/make/data/fontconfig/windows.fontconfig.properties b/src/java.desktop/windows/data/fontconfig/fontconfig.properties similarity index 100% rename from make/data/fontconfig/windows.fontconfig.properties rename to src/java.desktop/windows/data/fontconfig/fontconfig.properties diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp index 1a7a89fdef42573df2784182b9c3af8a73029bd4..3f019b0c2780e6c93af7b062d49f46ebb523a9af 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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 @@ -105,7 +105,7 @@ AwtButton* AwtButton::Create(jobject self, jobject parent) if (label == NULL) { labelStr = L""; } else { - labelStr = JNU_GetStringPlatformChars(env, label, JNI_FALSE); + labelStr = JNU_GetStringPlatformChars(env, label, NULL); } style = 0; @@ -311,7 +311,7 @@ void AwtButton::_SetLabel(void *param) if (label == NULL) { labelStr = TEXT(""); } else { - labelStr = JNU_GetStringPlatformChars(env, label, JNI_FALSE); + labelStr = JNU_GetStringPlatformChars(env, label, NULL); } if (labelStr == NULL) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp index d77ebb74a3e34c494a686d51ceeb49502ba878d0..5b004da95f20a7b232f4d77b8c9dad2c6651da58 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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 @@ -106,7 +106,7 @@ AwtCheckbox* AwtCheckbox::Create(jobject peer, jobject parent) label = (jstring)env->GetObjectField(target, AwtCheckbox::labelID); if (label != NULL) { - labelStr = JNU_GetStringPlatformChars(env, label, 0); + labelStr = JNU_GetStringPlatformChars(env, label, NULL); } if (labelStr != 0) { jint x = env->GetIntField(target, AwtComponent::xID); @@ -375,7 +375,7 @@ void AwtCheckbox::_SetLabel(void *param) } else { - labelStr = JNU_GetStringPlatformChars(env, label, JNI_FALSE); + labelStr = JNU_GetStringPlatformChars(env, label, NULL); } if (labelStr == NULL) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp index 73b3c51c79603cd65ed206302460d761cd8fb2df..9cf2cea6fabd7fd4d33aae31a5c447068f1125cb 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp @@ -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 @@ -75,9 +75,9 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WDesktopPeer_init JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_ShellExecute (JNIEnv *env, jclass cls, jstring fileOrUri_j, jstring verb_j) { - LPCWSTR fileOrUri_c = JNU_GetStringPlatformChars(env, fileOrUri_j, JNI_FALSE); + LPCWSTR fileOrUri_c = JNU_GetStringPlatformChars(env, fileOrUri_j, NULL); CHECK_NULL_RETURN(fileOrUri_c, NULL); - LPCWSTR verb_c = JNU_GetStringPlatformChars(env, verb_j, JNI_FALSE); + LPCWSTR verb_c = JNU_GetStringPlatformChars(env, verb_j, NULL); if (verb_c == NULL) { JNU_ReleaseStringPlatformChars(env, fileOrUri_j, fileOrUri_c); return NULL; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp index 33457ebef32c51a9af3e3d0ec0d31d5407c9847c..0afce8727e098a54b6bdd4331f934356422e23aa 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp @@ -28,20 +28,33 @@ #include "awt_Component.h" #include -static int signum(int i) { - // special version of signum which returns 1 when value is 0 - return i >= 0 ? 1 : -1; -} - static void MouseMove(jint x, jint y) { INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; mouseInput.mi.time = 0; - mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - mouseInput.mi.dx = (x * 65536 /::GetSystemMetrics(SM_CXSCREEN)) + signum(x); - mouseInput.mi.dy = (y * 65536 /::GetSystemMetrics(SM_CYSCREEN)) + signum(y); + + // The following calculations take into account a multi-monitor setup using + // a virtual screen for all monitors combined. + // More details from Microsoft are here -- + // https://docs.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen + + x -= ::GetSystemMetrics(SM_XVIRTUALSCREEN); + y -= ::GetSystemMetrics(SM_YVIRTUALSCREEN); + + mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | + MOUSEEVENTF_VIRTUALDESK; + + int scW = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + int scH = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + + // The following calculation to deduce mouse coordinates is based on + // empirical data + mouseInput.mi.dx = (x * 65536 + scW - 1) / scW; + mouseInput.mi.dy = (y * 65536 + scH - 1) / scH; + ::SendInput(1, &mouseInput, sizeof(mouseInput)); + } static void MousePress(jint buttonMask) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp index 434050215a34b0dcbf2b2ab30c7f90a6ba885ec7..ab8ad1ddf9e2ab3a9619129afe9b25b4c9898a24 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, 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 @@ -183,7 +183,7 @@ Java_sun_awt_Win32FontManager_registerFontWithPlatform(JNIEnv *env, jclass cl, jstring fontName) { - LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE); + LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, NULL); if (file) { ::AddFontResourceEx(file, FR_PRIVATE, NULL); JNU_ReleaseStringPlatformChars(env, fontName, file); @@ -203,7 +203,7 @@ Java_sun_awt_Win32FontManager_deRegisterFontWithPlatform(JNIEnv *env, jclass cl, jstring fontName) { - LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE); + LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, NULL); if (file) { ::RemoveFontResourceEx(file, FR_PRIVATE, NULL); JNU_ReleaseStringPlatformChars(env, fontName, file); diff --git a/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/src/java.management/share/classes/java/lang/management/ManagementFactory.java index 13db85d0f094cc3b10e07d40500a662f15981cb2..375f0ebb719b18dd8ecc405843237c9bb03eebb1 100644 --- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java +++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java @@ -936,8 +936,7 @@ public class ManagementFactory { all.add(new DefaultPlatformMBeanProvider()); return all; } - }, null, new FilePermission("<>", "read"), - new RuntimePermission("sun.management.spi.PlatformMBeanProvider.subclass")); + }, null, new FilePermission("<>", "read")); // load all platform components into a map var map = new HashMap>(); diff --git a/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java b/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java index 93779f0a811e3652fa8dda1e037144aa38ca467d..12472cabfccd363f3c0c155dcebb96e2f45eb099 100644 --- a/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java +++ b/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.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 @@ -203,15 +203,8 @@ public abstract class PlatformMBeanProvider { /** * Instantiates a new PlatformMBeanProvider. - * - * @throws SecurityException if the subclass (and calling code) does not - * have {@code RuntimePermission("sun.management.spi.PlatformMBeanProvider.subclass")} */ protected PlatformMBeanProvider () { - this(checkSubclassPermission()); - } - - private PlatformMBeanProvider(Void unused) { } /** @@ -222,13 +215,4 @@ public abstract class PlatformMBeanProvider { * MBeans provided by this provider. */ public abstract List> getPlatformComponentList(); - - private static Void checkSubclassPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission(PlatformMBeanProvider.class.getName()+".subclass")); - } - return null; - } } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java b/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java index 3c75f75519af56b00e322edfc2656831dc364a00..41144b132c087f982f71cde483a9e876f6820868 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.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 @@ -435,11 +435,10 @@ public final class StartTlsResponseImpl extends StartTlsResponse { /* * Pass up the cause of the failure */ - throw(SSLPeerUnverifiedException) - new SSLPeerUnverifiedException("hostname of the server '" + + throw new SSLPeerUnverifiedException("hostname of the server '" + hostname + "' does not match the hostname in the " + - "server's certificate.").initCause(e); + "server's certificate.", e); } } diff --git a/src/java.net.http/share/classes/java/net/http/HttpRequest.java b/src/java.net.http/share/classes/java/net/http/HttpRequest.java index fc9c10b14bc0b055397c9b82c542b4c2e627b3d8..974ea54717ee31cdfd3c4020aab6a81904679b8e 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpRequest.java +++ b/src/java.net.http/share/classes/java/net/http/HttpRequest.java @@ -292,6 +292,10 @@ public abstract class HttpRequest { /** * Builds and returns an {@link HttpRequest}. * + * @implSpec This method returns a new {@code HttpRequest} each time it is + * invoked. Once built, the {@code HttpRequest} is immutable and can be + * sent multiple times. + * * @return a new {@code HttpRequest} * @throws IllegalStateException if a URI has not been set */ diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java index 36af30050328367d2b59eb2a0f6a26b982e1d04e..8c9282c0579150b74ed2c0d80f6fa1de783afc92 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.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 @@ -144,14 +144,45 @@ final class Exchange { private volatile boolean closeRequested; void connection(HttpConnection connection) { - this.connection = connection; - if (closeRequested) closeConnection(); + boolean closeRequested; + synchronized (this) { + // check whether this new connection should be + // closed + closeRequested = this.closeRequested; + if (!closeRequested) { + this.connection = connection; + } else { + // assert this.connection == null + this.closeRequested = false; + } + } + if (closeRequested) closeConnection(connection); } void closeConnection() { - closeRequested = true; - HttpConnection connection = this.connection; - this.connection = null; + HttpConnection connection; + synchronized (this) { + connection = this.connection; + if (connection == null) { + closeRequested = true; + } else { + this.connection = null; + } + } + closeConnection(connection); + } + + HttpConnection disable() { + HttpConnection connection; + synchronized (this) { + connection = this.connection; + this.connection = null; + this.closeRequested = false; + } + return connection; + } + + private static void closeConnection(HttpConnection connection) { if (connection != null) { try { connection.close(); @@ -160,11 +191,6 @@ final class Exchange { } } } - - void disable() { - connection = null; - closeRequested = false; - } } // Called for 204 response - when no body is permitted @@ -524,8 +550,11 @@ final class Exchange { client.client2(), this, e::drainLeftOverBytes) .thenCompose((Http2Connection c) -> { + HttpConnection connection = connectionAborter.disable(); boolean cached = c.offerConnection(); - if (cached) connectionAborter.disable(); + if (!cached && connection != null) { + connectionAborter.connection(connection); + } Stream s = c.getStream(1); if (s == null) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java index 4101133a025d87c576bcbf4e2379f19034f6b540..c3861b2ad9fd3266b2610442501f7c123752df5f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.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 @@ -28,7 +28,6 @@ package jdk.internal.net.http; import java.io.EOFException; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.URI; import java.util.Base64; @@ -101,7 +100,7 @@ class Http2ClientImpl { Http2Connection connection = connections.get(key); if (connection != null) { try { - if (connection.closed || !connection.reserveStream(true)) { + if (!connection.isOpen() || !connection.reserveStream(true)) { if (debug.on()) debug.log("removing found closed or closing connection: %s", connection); deleteConnection(connection); @@ -153,7 +152,7 @@ class Http2ClientImpl { */ boolean offerConnection(Http2Connection c) { if (debug.on()) debug.log("offering to the connection pool: %s", c); - if (c.closed || c.finalStream()) { + if (!c.isOpen() || c.finalStream()) { if (debug.on()) debug.log("skipping offered closed or closing connection: %s", c); return false; @@ -161,6 +160,11 @@ class Http2ClientImpl { String key = c.key(); synchronized(this) { + if (!c.isOpen()) { + if (debug.on()) + debug.log("skipping offered closed or closing connection: %s", c); + return false; + } Http2Connection c1 = connections.putIfAbsent(key, c); if (c1 != null) { c.setFinalStream(); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 6a07d755e69684ba34138b7697e128295d7eccf4..8cd9db1210a5e7c041ff73c88a80c7857ae6d91c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -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 @@ -880,6 +880,10 @@ class Http2Connection { } } + boolean isOpen() { + return !closed && connection.channel().isOpen(); + } + void resetStream(int streamid, int code) { try { if (connection.channel().isOpen()) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index 6394b7b3cfa18bdcd29ead3d5dd38450eef607ac..fc2596e0aa4ec05812d5e6345a43d9e0f0bc44cd 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.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 @@ -573,9 +573,7 @@ final class HttpClientImpl extends HttpClient implements Trackable { throw ce; } else if (throwable instanceof SSLHandshakeException) { // special case for SSLHandshakeException - SSLHandshakeException he = new SSLHandshakeException(msg); - he.initCause(throwable); - throw he; + throw new SSLHandshakeException(msg, throwable); } else if (throwable instanceof SSLException) { // any other SSLException is wrapped in a plain // SSLException diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java index 42174ef9c44feacbed750301ba1dbc14bd7162fb..e72ba9d33dc1e3a201bc3c0e08a44314b18ccaf1 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.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 @@ -592,9 +592,7 @@ public class SSLTube implements FlowTube { engine.isOutboundDone(), handshakeFailed); - SSLHandshakeException e = new SSLHandshakeException(handshakeFailed); - if (t != null) e.initCause(t); - return e; + return new SSLHandshakeException(handshakeFailed, t); } @Override diff --git a/src/java.rmi/share/classes/java/rmi/server/LogStream.java b/src/java.rmi/share/classes/java/rmi/server/LogStream.java index 7d501ffb4af82884a3e6cdcfb03238bef3c3ba9b..ca554569d3b586b6dcafc80d70b6ed1a124d5999 100644 --- a/src/java.rmi/share/classes/java/rmi/server/LogStream.java +++ b/src/java.rmi/share/classes/java/rmi/server/LogStream.java @@ -176,7 +176,7 @@ public class LogStream extends PrintStream { synchronized (this) { synchronized (logOut) { // construct prefix for log messages: - buffer.setLength(0);; + buffer.setLength(0); buffer.append( // date/time stamp... (new Date()).toString()); buffer.append(':'); diff --git a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_de.properties b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_de.properties index e8f4189062c9d7808f116cacee83ebba5c5b31f2..ae2c6bf5cd1567c5db642d27ddf27b7bbdb5845e 100644 --- a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_de.properties +++ b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_de.properties @@ -1,6 +1,6 @@ # # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_ja.properties b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_ja.properties index ef6246e2e23795ea78950fe8db36bc6b173ec1fb..46261e666e4e3a7c0dbf705bf9cc4d4261a95129 100644 --- a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_ja.properties +++ b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_ja.properties @@ -1,6 +1,6 @@ # # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_zh_CN.properties b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_zh_CN.properties index 445d5ba87cd11635465081a72cdd9f92eda8bb7d..9a5a2bf4af467f91cae236fc2db26f4e8410c131 100644 --- a/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_zh_CN.properties +++ b/src/java.rmi/share/classes/sun/rmi/registry/resources/rmiregistry_zh_CN.properties @@ -1,6 +1,6 @@ # # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. # 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/make/data/jdwp/jdwp.spec b/src/java.se/share/data/jdwp/jdwp.spec similarity index 100% rename from make/data/jdwp/jdwp.spec rename to src/java.se/share/data/jdwp/jdwp.spec diff --git a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java index 1492033c49ce590b18720914302c2ac1c10da570..7bbb89544be3545849402241e6f1db6e141a6adf 100644 --- a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java +++ b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java @@ -101,7 +101,7 @@ import java.io.OutputStream; * * The stream-based methods of {@code GSSContext} have been deprecated in * Java SE 11. These methods have also been removed from - * + * * RFC 8353: Generic Security Service API Version 2: Java Bindings Update * for the following reasons (see section 11): "The overloaded methods of * GSSContext that use input and output streams as the means to convey diff --git a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java index 82f2391816bc2a8973537a72f485cf6d28bc0818..aa5795448c9b17b1236435358ebef0704e5b9e8d 100644 --- a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java +++ b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,9 +127,7 @@ public class NegotiatorImpl extends Negotiator { "fallback to other scheme if allowed. Reason:"); e.printStackTrace(); } - IOException ioe = new IOException("Negotiate support not initiated"); - ioe.initCause(e); - throw ioe; + throw new IOException("Negotiate support not initiated", e); } } @@ -157,9 +155,7 @@ public class NegotiatorImpl extends Negotiator { System.out.println("Negotiate support cannot continue. Reason:"); e.printStackTrace(); } - IOException ioe = new IOException("Negotiate support cannot continue"); - ioe.initCause(e); - throw ioe; + throw new IOException("Negotiate support cannot continue", e); } } } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java index 21b48d58fc226816f5d0e8dd8d200acda5a7ee16..d0acdd5c6e241ba211ef6863905a29fcd2c91978 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5MechFactory.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 @@ -146,8 +146,7 @@ public final class Krb5MechFactory implements MechanismFactory { SecurityManager sm = System.getSecurityManager(); if (sm != null) { String realm = (name.getKrb5PrincipalName()).getRealmAsString(); - String tgsPrincipal = - new String("krbtgt/" + realm + '@' + realm); + String tgsPrincipal = "krbtgt/" + realm + '@' + realm; ServicePermission perm = new ServicePermission(tgsPrincipal, "initiate"); try { diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java index ea2e24f6a8a060aaabb5ba210da0105e0a17f30c..b286f2c5844e70c83b0411884f3ba1b072a9c88f 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.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 @@ -63,7 +63,7 @@ public class Krb5NameElement /** * Instantiates a new Krb5NameElement object. Internally it stores the * information provided by the input parameters so that they may later - * be used for output when a printable representaion of this name is + * be used for output when a printable representation of this name is * needed in GSS-API format rather than in Kerberos format. * */ @@ -158,7 +158,7 @@ public class Krb5NameElement // Look for @ as in service@host // Assumes host name will not have an escaped '@' - int separatorPos = gssNameStr.lastIndexOf('@', gssNameStr.length()); + int separatorPos = gssNameStr.lastIndexOf('@'); // Not really a separator if it is escaped. Then this is just part // of the principal name or service name diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java b/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java index 917f0449f179aef1b0d67255ff19aada3d8e60e7..58cc98c14ecd82c6f64c8a0989e220fe7684fffe 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -497,13 +497,13 @@ public class EncryptionKey } public String toString() { - return new String("EncryptionKey: keyType=" + keyType - + " kvno=" + kvno - + " keyValue (hex dump)=" - + (keyValue == null || keyValue.length == 0 ? - " Empty Key" : '\n' - + Krb5.hexDumper.encodeBuffer(keyValue) - + '\n')); + return "EncryptionKey: keyType=" + keyType + + " kvno=" + kvno + + " keyValue (hex dump)=" + + (keyValue == null || keyValue.length == 0 ? + " Empty Key" : '\n' + + Krb5.hexDumper.encodeBuffer(keyValue) + + '\n'); } /** diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbCryptoException.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbCryptoException.java index 28522e8316dcc4c556abfbcd034ba73285ac6d05..eda5fcec397fc593eba8a8bfb0ec1ab668cc1061 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbCryptoException.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbCryptoException.java @@ -31,7 +31,7 @@ package sun.security.krb5; /** - * KrbCryptoExceptoin is a wrapper exception for exceptions thrown by JCE. + * KrbCryptoException is a wrapper exception for exceptions thrown by JCE. * * @author Yanni Zhang */ @@ -39,7 +39,7 @@ public class KrbCryptoException extends KrbException { private static final long serialVersionUID = -1657367919979982250L; - public KrbCryptoException (String s) { + public KrbCryptoException(String s) { super(s); } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java index 9350521609034713003311c140794d8bebb8cba9..206bbfc46f5e729ea71d5deb97cced18eafcd862 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,10 +234,8 @@ public class KRBError implements java.io.Serializable { System.out.println("Unable to parse eData field of KRB-ERROR:\n" + new sun.security.util.HexDumpEncoder().encodeBuffer(data)); } - IOException ioe = new IOException( - "Unable to parse eData field of KRB-ERROR"); - ioe.initCause(e); - throw ioe; + throw new IOException( + "Unable to parse eData field of KRB-ERROR", e); } } else { if (DEBUG) { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java index cb9912df6c287d940894bb4f9cdd4254984bade7..a8bda6008f6983006beb541090232c06c2f4f19c 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.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 @@ -29,7 +29,6 @@ import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import java.util.*; -import sun.security.krb5.EncryptedData; import sun.security.krb5.KrbCryptoException; import sun.security.krb5.Confounder; import sun.security.krb5.internal.crypto.KeyUsage; @@ -159,10 +158,7 @@ public class ArcFourCrypto extends DkCrypto { System.arraycopy(ss, 0, new_ss, 0, ss.length); Ksign = getHmac(baseKey, new_ss); } catch (Exception e) { - GeneralSecurityException gse = - new GeneralSecurityException("Calculate Checkum Failed!"); - gse.initCause(e); - throw gse; + throw new GeneralSecurityException("Calculate Checksum Failed!", e); } // get the salt using key usage @@ -173,10 +169,7 @@ public class ArcFourCrypto extends DkCrypto { try { messageDigest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { - GeneralSecurityException gse = - new GeneralSecurityException("Calculate Checkum Failed!"); - gse.initCause(e); - throw gse; + throw new GeneralSecurityException("Calculate Checksum Failed!", e); } messageDigest.update(salt); messageDigest.update(input, start, len); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java index 695268735a9d9f6230556ac2f98e19fb0a39ffff..d9cd765d12ef9a3bf49219df475800f559ef4d7d 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java @@ -134,8 +134,8 @@ public class AuthTime { * Encodes to be used in a dfl file */ protected byte[] encode0(String cstring, String sstring) { - byte[] c = cstring.getBytes(StandardCharsets.UTF_8);; - byte[] s = sstring.getBytes(StandardCharsets.UTF_8);; + byte[] c = cstring.getBytes(StandardCharsets.UTF_8); + byte[] s = sstring.getBytes(StandardCharsets.UTF_8); byte[] zero = new byte[1]; int len = 4 + c.length + 1 + 4 + s.length + 1 + 4 + 4; ByteBuffer bb = ByteBuffer.allocate(len) diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties index e1e43a16010cecd4df619ec025dcbaf7fe090f40..84fb41ce788818d1edc8149af2de40a2b491c45d 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -26,11 +26,11 @@ # CacheRowSetImpl exceptions cachedrowsetimpl.populate = Ung\u00FCltiges ResultSet-Objekt zum Auff\u00FCllen der Methode angegeben cachedrowsetimpl.invalidp = Ung\u00FCltiger Persistence-Provider generiert -cachedrowsetimpl.nullhash = CachedRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hash-Tabelle f\u00FCr Constructor angegeben +cachedrowsetimpl.nullhash = CachedRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle f\u00FCr Constructor angegeben cachedrowsetimpl.invalidop = Ung\u00FCltiger Vorgang beim Zeileneinf\u00FCgen cachedrowsetimpl.accfailed = acceptChanges nicht erfolgreich cachedrowsetimpl.invalidcp = Ung\u00FCltige Cursorposition -cachedrowsetimpl.illegalop = Ung\u00FCltiger Vorgang bei nicht eingef\u00FCgter Zeile +cachedrowsetimpl.illegalop = Unzul\u00E4ssiger Vorgang bei nicht eingef\u00FCgter Zeile cachedrowsetimpl.clonefail = Klonen nicht erfolgreich: {0} cachedrowsetimpl.invalidcol = Ung\u00FCltiger Spaltenindex cachedrowsetimpl.invalcolnm = Ung\u00FCltiger Spaltenname @@ -60,6 +60,7 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: keine Metadaten cachedrowsetimpl.movetoins2 = moveToInsertRow: ung\u00FCltige Spaltenanzahl cachedrowsetimpl.tablename = Tabellenname darf nicht null sein cachedrowsetimpl.keycols = Ung\u00FCltige Schl\u00FCsselspalten +cachedrowsetimpl.invalidcol = Ung\u00FCltiger Spaltenindex cachedrowsetimpl.opnotsupp = Vorgang nicht von Datenbank unterst\u00FCtzt cachedrowsetimpl.matchcols = \u00DCbereinstimmungsspalten entsprechen nicht den festgelegten Spalten cachedrowsetimpl.setmatchcols = \u00DCbereinstimmungsspalten m\u00FCssen vor dem Abrufen festgelegt werden @@ -79,7 +80,7 @@ cachedrowsetimpl.opnotysupp = Vorgang noch nicht unterst\u00FCtzt cachedrowsetimpl.featnotsupp = Feature nicht unterst\u00FCtzt # WebRowSetImpl exceptions -webrowsetimpl.nullhash = WebRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hash-Tabelle f\u00FCr Constructor angegeben +webrowsetimpl.nullhash = WebRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle f\u00FCr Constructor angegeben webrowsetimpl.invalidwr = Ung\u00FCltiger Writer webrowsetimpl.invalidrd = Ung\u00FCltiger Reader diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties index cd40ad2ef42837884eabb474a0044fe4eea56c98..3181e64c1ff686e9d91f544286ba202ea29575d0 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -60,6 +60,7 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \u30E1\u30BF\u30C7\u30FC\u30BF\u3 cachedrowsetimpl.movetoins2 = moveToInsertRow: \u7121\u52B9\u306A\u5217\u6570 cachedrowsetimpl.tablename = \u8868\u540D\u306Bnull\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 cachedrowsetimpl.keycols = \u7121\u52B9\u306A\u30AD\u30FC\u5217 +cachedrowsetimpl.invalidcol = \u7121\u52B9\u306A\u5217\u7D22\u5F15 cachedrowsetimpl.opnotsupp = \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u306A\u3044\u64CD\u4F5C cachedrowsetimpl.matchcols = \u4E00\u81F4\u5217\u304C\u5217\u306E\u30BB\u30C3\u30C8\u3068\u540C\u3058\u3067\u306F\u3042\u308A\u307E\u305B\u3093 cachedrowsetimpl.setmatchcols = \u4E00\u81F4\u5217\u3092\u53D6\u5F97\u3059\u308B\u524D\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties index a9f1203518caa09600b935d8d034bb505bc43db4..29d1823149dbc070f4c3b71559e681eb735a8804 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -60,6 +60,7 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \u65E0\u5143\u6570\u636E cachedrowsetimpl.movetoins2 = moveToInsertRow: \u5217\u6570\u65E0\u6548 cachedrowsetimpl.tablename = \u8868\u540D\u4E0D\u80FD\u4E3A\u7A7A\u503C cachedrowsetimpl.keycols = \u5173\u952E\u5B57\u5217\u65E0\u6548 +cachedrowsetimpl.invalidcol = \u5217\u7D22\u5F15\u65E0\u6548 cachedrowsetimpl.opnotsupp = \u64CD\u4F5C\u4E0D\u53D7\u6570\u636E\u5E93\u652F\u6301 cachedrowsetimpl.matchcols = \u5339\u914D\u5217\u4E0E\u8BBE\u7F6E\u7684\u90A3\u4E9B\u5339\u914D\u5217\u4E0D\u540C cachedrowsetimpl.setmatchcols = \u5728\u83B7\u53D6\u5339\u914D\u5217\u4E4B\u524D\u5148\u8BBE\u7F6E\u5339\u914D\u5217 diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java index a588c1dd94a8923213306d2ca812741449b0cd2e..21b9614d7466dd376774d51164e6c457ce937e4f 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java @@ -276,7 +276,7 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { // We assume caller is a CachedRowSet CachedRowSetImpl crs = (CachedRowSetImpl)caller; // crsResolve = new CachedRowSetImpl(); - this.crsResolve = new CachedRowSetImpl();; + this.crsResolve = new CachedRowSetImpl(); // The reader is registered with the writer at design time. // This is not required, in general. The reader has logic diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java index 136fff08d2a2c38303ce39f3aefdf4a015396f67..1affa2634ecc12c27e0f520694df5371bd93ff11 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java @@ -535,7 +535,7 @@ public class SQLOutputImpl implements SQLOutput { */ @SuppressWarnings("unchecked") public void writeStruct(Struct x) throws SQLException { - SerialStruct s = new SerialStruct(x,map);; + SerialStruct s = new SerialStruct(x,map); attribs.add(s); } diff --git a/src/java.sql/share/classes/java/sql/package-info.java b/src/java.sql/share/classes/java/sql/package-info.java index be494454a063d54accf73cc27c4d2787848f57bb..9e94e0b9393a1d5d46f2ef6f72ff6ab19cc0f490 100644 --- a/src/java.sql/share/classes/java/sql/package-info.java +++ b/src/java.sql/share/classes/java/sql/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, 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 @@ -334,7 +334,7 @@ * *

    diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java index 9b928794c6e44b32d6eeaba674e298670bf07fba..d2d63fc85ff5b14754b07ef81176958b30dc283e 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java @@ -160,7 +160,7 @@ public final class I18n { I18n.resourceBundle = ResourceBundle.getBundle( Constants.exceptionMessagesResourceBundleBase, - new Locale(languageCode, countryCode) + Locale.of(languageCode, countryCode) ); alreadyInitialized = true; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java index f71357900f7052bfb55841158bfea1d52071b756..07ea3779a20e94446efa7957affd15e05d17bf3a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java @@ -481,7 +481,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "Fehler: \"{\" darf nicht im Ausdruck enthalten sein"}, { ER_ILLEGAL_ATTRIBUTE , - "{0} hat ein ung\u00FCltiges Attribut: {1}"}, + "{0} hat ein unzul\u00E4ssiges Attribut: {1}"}, {ER_NULL_SOURCENODE_APPLYIMPORTS , "sourceNode ist null in xsl:apply-imports."}, @@ -526,7 +526,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "Namespace-Pr\u00E4fix kann nicht aufgel\u00F6st werden: {0}"}, { ER_ILLEGAL_VALUE, - "xml:space hat einen ung\u00FCltigen Wert: {0}"}, + "xml:space hat einen unzul\u00E4ssigen Wert: {0}"}, { ER_NO_OWNERDOC, "Der untergeordnete Knoten hat kein Eigent\u00FCmerdokument."}, @@ -646,7 +646,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "Element in Ergebnisbaum kann nicht erstellt werden: {0}"}, { ER_XMLSPACE_ILLEGAL_VALUE, - "xml:space in Quell-XML hat einen ung\u00FCltigen Wert: {0}"}, + "xml:space in Quell-XML hat einen unzul\u00E4ssigen Wert: {0}"}, { ER_NO_XSLKEY_DECLARATION, "Keine xsl:key-Deklaration f\u00FCr {0} vorhanden."}, @@ -673,7 +673,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "indent-result wird nicht mehr unterst\u00FCtzt. Verwenden Sie stattdessen xsl:output."}, { ER_ILLEGAL_ATTRIB, - "(StylesheetHandler) {0} hat ein ung\u00FCltiges Attribut: {1}"}, + "(StylesheetHandler) {0} hat ein unzul\u00E4ssiges Attribut: {1}"}, { ER_UNKNOWN_XSL_ELEM, "Unbekanntes XSL-Element: {0}"}, @@ -706,7 +706,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "(StylesheetHandler) {0} importiert sich direkt oder indirekt selbst."}, { ER_XMLSPACE_ILLEGAL_VAL, - "(StylesheetHandler) xml:space hat einen ung\u00FCltigen Wert: {0}"}, + "(StylesheetHandler) xml:space hat einen unzul\u00E4ssigen Wert: {0}"}, { ER_PROCESSSTYLESHEET_NOT_SUCCESSFUL, "processStylesheet nicht erfolgreich."}, @@ -740,7 +740,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "Pr\u00E4fix in exclude-result-prefixes ist nicht g\u00FCltig: {0}"}, { ER_MISSING_NS_URI, - "Fehlender Namespace-URI f\u00FCr angegebenes Pr\u00E4fix"}, + "Fehlende Namespace-URI f\u00FCr angegebenes Pr\u00E4fix"}, { ER_MISSING_ARG_FOR_OPTION, "Fehlendes Argument f\u00FCr Option: {0}"}, @@ -872,7 +872,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "Stylesheet-Root wurde nicht gefunden."}, { ER_ILLEGAL_XMLSPACE_VALUE, - "Ung\u00FCltiger Wert f\u00FCr xml:space"}, + "Unzul\u00E4ssiger Wert f\u00FCr xml:space"}, { ER_PROCESSFROMNODE_FAILED, "processFromNode nicht erfolgreich"}, @@ -990,7 +990,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "{0}-Attributwert nicht erkannt "}, { ER_NULL_URI_NAMESPACE, - "Versuch, ein Namespace-Pr\u00E4fix mit einem Null-URI zu generieren"}, + "Versuch, ein Namespace-Pr\u00E4fix mit einer Null-URI zu generieren"}, { ER_NUMBER_TOO_BIG, "Versuch, eine Zahl zu formatieren, die gr\u00F6\u00DFer als die gr\u00F6\u00DFte Long-Ganzzahl ist"}, @@ -1272,7 +1272,7 @@ public class XSLTErrorResources_de extends ListResourceBundle "xsl:decimal-format-Namen m\u00FCssen eindeutig sein. Name \"{0}\" wurde dupliziert."}, { WG_ILLEGAL_ATTRIBUTE, - "{0} hat ein ung\u00FCltiges Attribut: {1}"}, + "{0} hat ein unzul\u00E4ssiges Attribut: {1}"}, { WG_COULD_NOT_RESOLVE_PREFIX, "Namespace-Pr\u00E4fix konnte nicht aufgel\u00F6st werden: {0}. Der Knoten wird ignoriert."}, @@ -1281,10 +1281,10 @@ public class XSLTErrorResources_de extends ListResourceBundle "xsl:stylesheet erfordert ein \"version\"-Attribut."}, { WG_ILLEGAL_ATTRIBUTE_NAME, - "Ung\u00FCltiger Attributname: {0}"}, + "Unzul\u00E4ssiger Attributname: {0}"}, { WG_ILLEGAL_ATTRIBUTE_VALUE, - "Ung\u00FCltiger Wert f\u00FCr Attribut {0}: {1}"}, + "Unzul\u00E4ssiger Wert f\u00FCr Attribut {0}: {1}"}, { WG_EMPTY_SECOND_ARG, "Resultierendes NodeSet aus zweitem Argument von Dokumentfunktion ist leer. Geben Sie ein leeres NodeSet zur\u00FCck."}, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java index ab12a274a46eb5c84d9276e45fc66aff7adaaa7f..e0259cb8c3f4c36a661756880754abe1b429768d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java @@ -1011,7 +1011,7 @@ public class XPathParser extends lr_parser { if (axis == Axis.NAMESPACE) { nodeType = (name.toString().equals("*")) ? -1 - : _xsltc.registerNamespacePrefix(name);; + : _xsltc.registerNamespacePrefix(name); } else { final String uri = name.getNamespace(); final String local = name.getLocalPart(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java index 425707e4792ca3ef5e029faadd3b8a95055d48be..ea6eecee48dcf4a9daf0085c48b641f3dfe594ad 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java @@ -167,7 +167,7 @@ public class ErrorMessages_de extends ListResourceBundle { * mentioned in the substitution text is not well-formed syntactically. */ {ErrorMsg.INVALID_URI_ERR, - "Ung\u00FCltiger URI \"{0}\"."}, + "Ung\u00FCltige URI \"{0}\"."}, /* * Note to translators: This message is displayed when the URI @@ -234,7 +234,7 @@ public class ErrorMessages_de extends ListResourceBundle { * text is the offending character. */ {ErrorMsg.ILLEGAL_CHAR_ERR, - "Ung\u00FCltiges Zeichen \"{0}\" in XPath-Ausdruck."}, + "Unzul\u00E4ssiges Zeichen \"{0}\" in XPath-Ausdruck."}, /* * Note to translators: A processing instruction is a mark-up item in @@ -243,7 +243,7 @@ public class ErrorMessages_de extends ListResourceBundle { * text is the name. */ {ErrorMsg.ILLEGAL_PI_ERR, - "Ung\u00FCltiger Name \"{0}\" f\u00FCr Verarbeitungsanweisung."}, + "Unzul\u00E4ssiger Name \"{0}\" f\u00FCr Verarbeitungsanweisung."}, /* * Note to translators: This message is reported if the stylesheet @@ -261,7 +261,7 @@ public class ErrorMessages_de extends ListResourceBundle { * text. */ {ErrorMsg.ILLEGAL_ATTRIBUTE_ERR, - "Ung\u00FCltiges Attribut \"{0}\"."}, + "Unzul\u00E4ssiges Attribut \"{0}\"."}, /* * Note to translators: "import" and "include" are keywords that should @@ -321,7 +321,7 @@ public class ErrorMessages_de extends ListResourceBundle { * function has too many or too few arguments. */ {ErrorMsg.ILLEGAL_ARG_ERR, - "Ung\u00FCltige Argumente f\u00FCr Funktionsaufruf."}, + "Unzul\u00E4ssige Argumente f\u00FCr Funktionsaufruf."}, /* * Note to translators: "document()" is the name of function and must @@ -383,7 +383,7 @@ public class ErrorMessages_de extends ListResourceBundle { * element of a type that it was not permitted to contain. */ {ErrorMsg.ILLEGAL_CHILD_ERR, - "Ung\u00FCltiges untergeordnetes Element."}, + "Unzul\u00E4ssiges untergeordnetes Element."}, /* * Note to translators: The stylesheet tried to create an element with diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/CollatorFactoryBase.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/CollatorFactoryBase.java index ce50940962055ed280ef1d481b0fa42c1498ba0b..1cfd9693901b741b3576d4085cd13945da49c048 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/CollatorFactoryBase.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/CollatorFactoryBase.java @@ -38,7 +38,7 @@ public class CollatorFactoryBase implements CollatorFactory { } public Collator getCollator(String lang, String country) { - return Collator.getInstance(new Locale(lang, country)); + return Collator.getInstance(Locale.of(lang, country)); } public Collator getCollator(Locale locale) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java index 6b44ace762dcfbe3ac19d332c7ac94f77c5dc919..dadea4ba3b00c259756975ea6c5cc3797b499c48 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java @@ -149,7 +149,7 @@ public class ErrorMessages_de extends ListResourceBundle { * iterator. (See definition of iterator above.) */ {BasisLibrary.ITERATOR_CLONE_ERR, - "Iterator \"{0}\" kann nicht geclont werden."}, + "Iterator \"{0}\" kann nicht geklont werden."}, /* * Note to translators: The following represents an internal error diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java index 4fc9a71b157de69c5c9a43b9c5496c480d753238..98c2c01310ce32ce44172e548f09729399b921bf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.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 @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.sun.org.apache.xerces.internal.impl; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; @@ -39,29 +38,31 @@ import jdk.xml.internal.JdkProperty; import jdk.xml.internal.JdkXmlUtils; /** - * This class manages different properties related to Stax specification and its implementation. - * This class constructor also takes itself (PropertyManager object) as parameter and initializes the - * object with the property taken from the object passed. + * This class manages the properties for the Stax specification and its + * implementation. A PropertyManager object can be constructed based on the + * context or initialized with another PropertyManager object. * * @author Neeraj Bajaj * @author K Venugopal * @author Sunitha Reddy */ - public class PropertyManager { - public static final String STAX_NOTATIONS = "javax.xml.stream.notations"; public static final String STAX_ENTITIES = "javax.xml.stream.entities"; private static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning"; - /** Property identifier: Security manager. */ + /** + * Property identifier: Security manager. + */ private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER; - /** Property identifier: Security property manager. */ - private static final String XML_SECURITY_PROPERTY_MANAGER = - JdkConstants.XML_SECURITY_PROPERTY_MANAGER; + /** + * Property identifier: Security property manager. + */ + private static final String XML_SECURITY_PROPERTY_MANAGER + = JdkConstants.XML_SECURITY_PROPERTY_MANAGER; HashMap supportedProps = new HashMap<>(); @@ -71,14 +72,18 @@ public class PropertyManager { public static final int CONTEXT_READER = 1; public static final int CONTEXT_WRITER = 2; - /** Creates a new instance of PropertyManager */ + /** + * Creates a new instance of the PropertyManager based on the context. + * + * @param context a flag indicating the context: for a reader or writer. + */ public PropertyManager(int context) { - switch(context){ - case CONTEXT_READER:{ + switch (context) { + case CONTEXT_READER: { initConfigurableReaderProperties(); break; } - case CONTEXT_WRITER:{ + case CONTEXT_WRITER: { initWriterProps(); break; } @@ -86,28 +91,29 @@ public class PropertyManager { } /** - * Initialize this object with the properties taken from passed PropertyManager object. + * Initializes the object with the properties of another + * PropertyManager object. + * + * @param propertyManager another PropertyManager object */ - public PropertyManager(PropertyManager propertyManager){ + public PropertyManager(PropertyManager propertyManager) { HashMap properties = propertyManager.getProperties(); supportedProps.putAll(properties); - fSecurityManager = (XMLSecurityManager)getProperty(SECURITY_MANAGER); - fSecurityPropertyMgr = (XMLSecurityPropertyManager)getProperty(XML_SECURITY_PROPERTY_MANAGER); + fSecurityManager = (XMLSecurityManager) getProperty(SECURITY_MANAGER); + fSecurityPropertyMgr = (XMLSecurityPropertyManager) getProperty(XML_SECURITY_PROPERTY_MANAGER); } - private HashMap getProperties(){ - return supportedProps ; + private HashMap getProperties() { + return supportedProps; } - /** - * Important point: - * 1. We are not exposing Xerces namespace property. Application should configure namespace through - * Stax specific property. + * Initializes reader properties. * + * @implNote: StAX defined namespace rather than Xerces' should be used. */ - private void initConfigurableReaderProperties(){ + private void initConfigurableReaderProperties() { //spec default values supportedProps.put(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE); supportedProps.put(XMLInputFactory.IS_VALIDATING, Boolean.FALSE); @@ -118,18 +124,18 @@ public class PropertyManager { supportedProps.put(XMLInputFactory.REPORTER, null); supportedProps.put(XMLInputFactory.RESOLVER, null); supportedProps.put(XMLInputFactory.ALLOCATOR, null); - supportedProps.put(STAX_NOTATIONS,null ); + supportedProps.put(STAX_NOTATIONS, null); //zephyr (implementation) specific properties which can be set by the application. //interning is always done - supportedProps.put(Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE , true); + supportedProps.put(Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE, true); //recognizing java encoding names by default - supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE, true) ; + supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE, true); //in stax mode, namespace declarations are not added as attributes - supportedProps.put(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE , Boolean.FALSE) ; + supportedProps.put(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE, Boolean.FALSE); supportedProps.put(Constants.READER_IN_DEFINED_STATE, true); supportedProps.put(Constants.REUSE_INSTANCE, true); - supportedProps.put(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.STAX_REPORT_CDATA_EVENT , false); + supportedProps.put(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.STAX_REPORT_CDATA_EVENT, false); supportedProps.put(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.IGNORE_EXTERNAL_DTD, Boolean.FALSE); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE, false); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE, false); @@ -142,61 +148,89 @@ public class PropertyManager { // Initialize Catalog features supportedProps.put(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT); - for( CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) { + for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) { supportedProps.put(f.getPropertyName(), null); } supportedProps.put(JdkConstants.CDATA_CHUNK_SIZE, JdkConstants.CDATA_CHUNK_SIZE_DEFAULT); } - private void initWriterProps(){ - supportedProps.put(XMLOutputFactory.IS_REPAIRING_NAMESPACES , Boolean.FALSE); + /** + * Initializes writer properties. + */ + private void initWriterProps() { + supportedProps.put(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE); //default value of escaping characters is 'true' - supportedProps.put(Constants.ESCAPE_CHARACTERS , Boolean.TRUE); + supportedProps.put(Constants.ESCAPE_CHARACTERS, Boolean.TRUE); supportedProps.put(Constants.REUSE_INSTANCE, true); } /** - * public void reset(){ - * supportedProps.clear() ; - * } + * Checks whether a property is managed by the PropertyManager. + * + * @param property the name of a property + * @return true if the property is managed by the PropertyManager, false + * otherwise */ - public boolean containsProperty(String property){ - return supportedProps.containsKey(property) || - (fSecurityManager != null && fSecurityManager.getIndex(property) > -1) || - (fSecurityPropertyMgr!=null && fSecurityPropertyMgr.getIndex(property) > -1) ; + public boolean containsProperty(String property) { + return supportedProps.containsKey(property) + || (fSecurityManager != null && fSecurityManager.getIndex(property) > -1) + || (fSecurityPropertyMgr != null && fSecurityPropertyMgr.getIndex(property) > -1); } - public Object getProperty(String property){ - /** Check to see if the property is managed by the security manager **/ - String propertyValue = (fSecurityManager != null) ? - fSecurityManager.getLimitAsString(property) : null; + /** + * Returns the value of a property. + * + * @param property the name of the property + * @return the value of a property + */ + public Object getProperty(String property) { + /** + * Check to see if the property is managed by the security manager * + */ + String propertyValue = (fSecurityManager != null) + ? fSecurityManager.getLimitAsString(property) : null; + /** + * Check to see if the property is managed by the security property + * manager + */ + if (propertyValue == null) { + propertyValue = (fSecurityPropertyMgr != null) + ? fSecurityPropertyMgr.getValue(property) : null; + } return propertyValue != null ? propertyValue : supportedProps.get(property); } - public void setProperty(String property, Object value){ - String equivalentProperty = null ; - if(property.equals(XMLInputFactory.IS_NAMESPACE_AWARE)){ - equivalentProperty = Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE ; - } - else if(property.equals(XMLInputFactory.IS_VALIDATING)){ - if( (value instanceof Boolean) && ((Boolean)value).booleanValue()){ - throw new java.lang.IllegalArgumentException("true value of isValidating not supported") ; + /** + * Sets a property value. + * + * @param property the name of the property + * @param value the value of the property + */ + public void setProperty(String property, Object value) { + String equivalentProperty = null; + if (property.equals(XMLInputFactory.IS_NAMESPACE_AWARE)) { + equivalentProperty = Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; + } else if (property.equals(XMLInputFactory.IS_VALIDATING)) { + if ((value instanceof Boolean) && ((Boolean) value)) { + throw new IllegalArgumentException("true value of isValidating not supported"); } - } - else if(property.equals(STRING_INTERNING)){ - if( (value instanceof Boolean) && !((Boolean)value).booleanValue()){ - throw new java.lang.IllegalArgumentException("false value of " + STRING_INTERNING + "feature is not supported") ; + } else if (property.equals(STRING_INTERNING)) { + if ((value instanceof Boolean) && !((Boolean) value)) { + throw new IllegalArgumentException("false value of " + + STRING_INTERNING + "feature is not supported"); } - } - else if(property.equals(XMLInputFactory.RESOLVER)){ + } else if (property.equals(XMLInputFactory.RESOLVER)) { //add internal stax property - supportedProps.put( Constants.XERCES_PROPERTY_PREFIX + Constants.STAX_ENTITY_RESOLVER_PROPERTY , new StaxEntityResolverWrapper((XMLResolver)value)) ; + supportedProps.put(Constants.XERCES_PROPERTY_PREFIX + + Constants.STAX_ENTITY_RESOLVER_PROPERTY, + new StaxEntityResolverWrapper((XMLResolver) value)); } /** - * It's possible for users to set a security manager through the interface. - * If it's the old SecurityManager, convert it to the new XMLSecurityManager + * It's possible for users to set a security manager through the + * interface. If it's the old SecurityManager, convert it to the new + * XMLSecurityManager */ if (property.equals(Constants.SECURITY_MANAGER)) { fSecurityManager = XMLSecurityManager.convert(value, fSecurityManager); @@ -207,29 +241,30 @@ public class PropertyManager { if (value == null) { fSecurityPropertyMgr = new XMLSecurityPropertyManager(); } else { - fSecurityPropertyMgr = (XMLSecurityPropertyManager)value; + fSecurityPropertyMgr = (XMLSecurityPropertyManager) value; } supportedProps.put(JdkConstants.XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); return; } //check if the property is managed by security manager - if (fSecurityManager == null || - !fSecurityManager.setLimit(property, JdkProperty.State.APIPROPERTY, value)) { + if (fSecurityManager == null + || !fSecurityManager.setLimit(property, JdkProperty.State.APIPROPERTY, value)) { //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null || - !fSecurityPropertyMgr.setValue(property, XMLSecurityPropertyManager.State.APIPROPERTY, value)) { + if (fSecurityPropertyMgr == null + || !fSecurityPropertyMgr.setValue(property, XMLSecurityPropertyManager.State.APIPROPERTY, value)) { //fall back to the existing property manager supportedProps.put(property, value); } } - if(equivalentProperty != null){ - supportedProps.put(equivalentProperty, value ) ; + if (equivalentProperty != null) { + supportedProps.put(equivalentProperty, value); } } - public String toString(){ + @Override + public String toString() { return supportedProps.toString(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index 33ffe9831b86ea016bbc973e0f778b0bd2ea1de5..5fb78877e21644d4ab146c2fe5cdd4a0050dd96b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.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. */ /* @@ -57,7 +57,7 @@ import java.util.Locale; * @author Arnaud Le Hors, IBM * @author K.Venugopal Sun Microsystems * - * @LastModified: Sep 2021 + * @LastModified: Mar 2022 */ public class XMLEntityScanner implements XMLLocator { @@ -2162,7 +2162,7 @@ public class XMLEntityScanner implements XMLLocator { break; } } - if (c == '\r') { + if (c == '\r' && isExternal) { int cc = fCurrentEntity.ch[fCurrentEntity.position]; if (cc == '\n' || (version == XML_VERSION_1_1 && cc == 0x85)) { fCurrentEntity.position++; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties index 0b8ee27b51ef64d734364dd6c2336c9520c331e5..5b802e6ea58ef6faeded656644771cd767543d3d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # DOM implementation. # @@ -39,7 +14,7 @@ HIERARCHY_REQUEST_ERR = Es wurde versucht, einen Knoten an einer Stelle einzuf\ INDEX_SIZE_ERR = Index oder Gr\u00F6\u00DFe ist negativ oder gr\u00F6\u00DFer als der zul\u00E4ssige Wert. INUSE_ATTRIBUTE_ERR = Es wurde versucht, ein Attribut hinzuzuf\u00FCgen, das bereits an einer anderen Stelle verwendet wird. INVALID_ACCESS_ERR = Ein Parameter oder Vorgang wird nicht vom zugrunde liegenden Objekt unterst\u00FCtzt. -INVALID_CHARACTER_ERR = Ung\u00FCltiges XML-Zeichen angegeben. +INVALID_CHARACTER_ERR = Ung\u00FCltiges oder unzul\u00E4ssiges XML-Zeichen angegeben. INVALID_MODIFICATION_ERR = Es wurde versucht, den Typ des zugrunde liegenden Objekts zu \u00E4ndern. INVALID_STATE_ERR = Es wurde versucht, ein Objekt zu \u00E4ndern, das nicht verwendet werden kann. NAMESPACE_ERR = Es wurde versucht, ein Objekt auf eine Weise zu erstellen oder zu \u00E4ndern, die falsch in Bezug auf Namespaces ist. @@ -47,7 +22,7 @@ NOT_FOUND_ERR = Es wurde versucht, einen Knoten in einem Kontext zu referenziere NOT_SUPPORTED_ERR = Der angeforderte Typ des Objekts oder Vorgangs wird nicht von der Implementierung unterst\u00FCtzt. NO_DATA_ALLOWED_ERR = Daten wurden f\u00FCr einen Knoten angegeben, der keine Daten unterst\u00FCtzt. NO_MODIFICATION_ALLOWED_ERR = Es wurde versucht, ein Objekt zu \u00E4ndern, bei dem \u00C4nderungen nicht zul\u00E4ssig sind. -SYNTAX_ERR = Ung\u00FCltige Zeichenfolge angegeben. +SYNTAX_ERR = Ung\u00FCltige oder unzul\u00E4ssige Zeichenfolge angegeben. VALIDATION_ERR = Aufruf einer Methode wie insertBefore oder removeChild w\u00FCrde die Dokumentgrammatik des Knotens ung\u00FCltig machen. WRONG_DOCUMENT_ERR = Ein Knoten wird in einem anderen Dokument verwendet als dem, von dem er erstellt wurde. TYPE_MISMATCH_ERR = Der Werttyp f\u00FCr diesen Parameternamen ist nicht mit dem erwarteten Werttyp kompatibel. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties index e2f923e618158366d37a36c3ad131176f7b76a10..c6fe53e399b0bc9f3f089f0e5116b100a8ac82d2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # DOM implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties index c59decb1b3de7a5ae63fbdd10b1bd06f13691008..2f74f54fbaba5c5c8953b717a8013f0d750db200 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # DOM implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties index 1d9f1a082fac474cdf1f08d2cb227fdcdad64e72..4bbbaea3b1ffc9c87465163e6f3058aa9eb93533 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties index 84d90d0fd416b3f939efb41a39fd647ee063aa3d..a8ef5dbddc0774cd75e5a45bfeb30b612858ef31 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties index 21a3e3c99190f41870e67d57a7075bdf539a6bb0..e5b9aca2e702e15100340d2f2ef6b580f7af46e7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties index d9a740adbd805f85da6c4668b9b9f41e9952a705..820fc8fb2e3dc5951230f44bff32900c94792ec4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties index 86120a72476e538ea8a9b79ebb4ec7aa309e3318..267c886ffed92d127e725354990163ca63f1fafd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties index 9cc5ccb25f2fb60601bfff8d505fe5265d2678e4..9ffbd1c608e1a72b8ecc4652a9ddaf89df22cb85 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties index 2b99e3461e1e4e9aba0c5c9ee4f8545a29e0a529..4f6a8717006b3f0a60395cfa06ab386cb27d1ad7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties index 21978c587cb20d3051f8a58b19db753e5a1f6206..0c6c98dc312b4bcbe1ef4cc6fb9aa305ea8a865d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties index cc07506f88800d593b68fa54a3678384f9b3664d..0d6e7a122428ddcea6a13ea98ac9236a91275a90 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties index 45c47c62709cceb081fbaec9bf5275c90bc14855..412d96f917e259c041c7abf2f31a26d87b3c42a4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 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. 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. -# - # Messages for message reporting BadMessageKey = Die zum Meldungsschl\u00FCssel geh\u00F6rige Fehlermeldung kann nicht gefunden werden. FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n @@ -51,7 +26,7 @@ MultipleRootElements = Ein ordnungsgem\u00E4\u00DF formatiertes Dokument darf ni ContentIllegalAtTopLevel = Der Ersatz eines "include"-Elements, das als Dokumentelement im Quell-Infoset der obersten Ebene angezeigt wird, darf keine Zeichen enthalten. UnexpandedEntityReferenceIllegal = Der Ersatz eines "include"-Elements, das als Dokumentelement im Quell-Infoset der obersten Ebene angezeigt wird, darf keine nicht erweiterten Entityreferenzen enthalten. HrefFragmentIdentifierIllegal = Fragment-IDs d\u00FCrfen nicht verwendet werden. Der "href"-Attributwert "{0}" ist nicht zul\u00E4ssig. -HrefSyntacticallyInvalid = "href"-Attributwert "{0}" hat eine ung\u00FCltige Syntax. Nach Anwenden der Escape-Regeln ist der Wert kein syntaktisch korrekter URI oder IRI. +HrefSyntacticallyInvalid = "href"-Attributwert "{0}" hat eine ung\u00FCltige Syntax. Nach Anwenden der Escape-Regeln ist der Wert keine syntaktisch korrekte URI oder IRI. XPointerStreamability = Es wurde ein xpointer angegeben, der auf eine Stelle im Quell-Infoset verweist. Auf diese Stelle kann aufgrund des Streamingcharakters des Prozessors nicht zugegriffen werden. XPointerResolutionUnsuccessful = XPointer-Aufl\u00F6sung nicht erfolgreich. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties index 2034e72751e73eeba4d58cfde49cc2c7f316bbc2..55abfda9b23fb2a7787cb1acbdfd2b25c2fe0a9e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - # Messages for message reporting BadMessageKey = \u30E1\u30C3\u30BB\u30FC\u30B8\u30FB\u30AD\u30FC\u306B\u5BFE\u5FDC\u3059\u308B\u30A8\u30E9\u30FC\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 FormatFailed = \u6B21\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u66F8\u5F0F\u8A2D\u5B9A\u4E2D\u306B\u5185\u90E8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:\n diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties index 3231b7318926104db9de348d154e3cde5dab2f9f..8e32a7337a18c150c19c5109e4e646381312161a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - # Messages for message reporting BadMessageKey = \u627E\u4E0D\u5230\u4E0E\u6D88\u606F\u5173\u952E\u5B57\u5BF9\u5E94\u7684\u9519\u8BEF\u6D88\u606F\u3002 FormatFailed = \u8BBE\u7F6E\u4EE5\u4E0B\u6D88\u606F\u7684\u683C\u5F0F\u65F6\u51FA\u73B0\u5185\u90E8\u9519\u8BEF:\n diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index e535ffc74b2cf600334f0dd97dac8d44c4cbe3e4..3848d68aa2e02d51a30f80842b3e086c96e31362 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -123,7 +123,7 @@ InvalidHighSurrogate = High-Surrogate-Bits in UTF-8-Sequenz d\u00FCrfen 0x10 nicht \u00FCberschreiten, gefunden wurde aber 0x{0}. OperationNotSupported = Vorgang "{0}" nicht unterst\u00FCtzt von {1}-Reader. InvalidASCII = Byte "{0}" geh\u00F6rt nicht zum (7-Bit) ASCII-Zeichensatz. - CharConversionFailure = Eine Entity, f\u00FCr die eine bestimmte Codierung ermittelt wurde, darf keine Sequenzen enthalten, die in dieser Codierung ung\u00FCltig sind. + CharConversionFailure = Eine Entity, f\u00FCr die eine bestimmte Codierung ermittelt wurde, darf keine Sequenzen enthalten, die in dieser Codierung unzul\u00E4ssig sind. # DTD Messages # 2.2 Characters @@ -278,7 +278,7 @@ # Namespaces support # 4. Using Qualified Names - IllegalQName = Element oder Attribut stimmt nicht mit QName-Production \u00FCberein: QName::=(NCName':')?NCName. + IllegalQName = Element oder Attribut "{0}" stimmt nicht mit QName-Produktion \u00FCberein: QName::=(NCName'':'')?NCName. ElementXMLNSPrefix = Element "{0}" darf nicht "xmlns" als Pr\u00E4fix enthalten. ElementPrefixUnbound = Pr\u00E4fix "{0}" f\u00FCr Element "{1}" ist nicht gebunden. AttributePrefixUnbound = Pr\u00E4fix "{2}" f\u00FCr Attribut "{1}", das mit Elementtyp "{0}" verkn\u00FCpft ist, ist nicht gebunden. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties index 859b35309087ef96c6cb667963a8ab250a1d9696..7001ef4526606eae8571d40586439d2c01787b1c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties @@ -278,7 +278,7 @@ # Namespaces support # 4. Using Qualified Names - IllegalQName = \u8981\u7D20\u307E\u305F\u306F\u5C5E\u6027\u304CQName\u751F\u6210\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093: QName::=(NCName':')?NCName\u3002 + IllegalQName = \u8981\u7D20\u307E\u305F\u306F\u5C5E\u6027"{0}"\u304CQName\u751F\u6210\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093: QName::=(NCName'':'')?NCName\u3002 ElementXMLNSPrefix = \u8981\u7D20"{0}"\u306E\u63A5\u982D\u8F9E\u3068\u3057\u3066"xmlns"\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002 ElementPrefixUnbound = \u8981\u7D20"{1}"\u306E\u63A5\u982D\u8F9E"{0}"\u304C\u30D0\u30A4\u30F3\u30C9\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 AttributePrefixUnbound = \u8981\u7D20\u30BF\u30A4\u30D7"{0}"\u306B\u95A2\u9023\u4ED8\u3051\u3089\u308C\u3066\u3044\u308B\u5C5E\u6027"{1}"\u306E\u63A5\u982D\u8F9E"{2}"\u304C\u30D0\u30A4\u30F3\u30C9\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties index 781b2c640c826075ab0310a4222e0075720e2faa..ac05ad875c6525c7692bdef5f7c0703adb1f7c38 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties @@ -278,7 +278,7 @@ # Namespaces support # 4. Using Qualified Names - IllegalQName = \u5143\u7D20\u6216\u5C5E\u6027\u4E0D\u5339\u914D QName \u751F\u4EA7: QName::=(NCName':')?NCName\u3002 + IllegalQName = \u5143\u7D20\u6216\u5C5E\u6027 "{0}" \u4E0D\u5339\u914D QName \u751F\u4EA7\uFF1AQName::=(NCName'':'')?NCName\u3002 ElementXMLNSPrefix = \u5143\u7D20 "{0}" \u4E0D\u80FD\u4F7F\u7528 "xmlns" \u4F5C\u4E3A\u524D\u7F00\u3002 ElementPrefixUnbound = \u5143\u7D20 "{1}" \u7684\u524D\u7F00 "{0}" \u672A\u7ED1\u5B9A\u3002 AttributePrefixUnbound = \u4E0E\u5143\u7D20\u7C7B\u578B "{0}" \u76F8\u5173\u8054\u7684\u5C5E\u6027 "{1}" \u7684\u524D\u7F00 "{2}" \u672A\u7ED1\u5B9A\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 7c864068a949d15dcf58cd1a9459be463dcffb5c..9ca2596f92edf15f13191de7c0fca201ae08e7a0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. @@ -64,7 +39,6 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: Content des Elements ''{0}'' ist nicht vollst\u00E4ndig. ''{1}'' wird erwartet. cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: \u00DCbereinstimmungsplatzhalter ist streng, aber es kann keine Deklaration f\u00FCr Element ''{0}'' gefunden werden. cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Ung\u00FCltiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element erwartet. - cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: Ung\u00FCltiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element ''{1}'' erwartet. cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: "{0}" darf maximal "{2}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde \u00FCberschritten. An dieser Stelle wird eines von "{1}" erwartet. cvc-complex-type.2.4.f = cvc-complex-type.2.4.e: "{0}" darf maximal "{1}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde \u00FCberschritten. An dieser Stelle wird kein untergeordnetes Element erwartet. cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Ung\u00FCltigen Inhalt gefunden, der mit Element "{0}" beginnt. "{1}" soll erwartungsgem\u00E4\u00DF mindestens "{2}"-mal in der aktuellen Abfolge auftreten. Eine weitere Instanz ist erforderlich, um diesen Constraint zu erf\u00FCllen. @@ -259,14 +233,14 @@ rcase-MapAndSum.2 = rcase-MapAndSum.2: Vorkommensbereich der Gruppe ({0},{1}) ist keine g\u00FCltige Einschr\u00E4nkung des Vorkommensbereichs der Basisgruppe ({2},{3}). rcase-NameAndTypeOK.1 = rcase-NameAndTypeOK.1: Elemente haben Namen und Ziel-Namespaces, die nicht identisch sind: Element ''{0}'' in Namespace ''{1}'' und Element ''{2}'' in Namespace ''{3}''. rcase-NameAndTypeOK.2 = rcase-NameAndTypeOK.2: Fehler beim Partikel, dessen '{'term'}' die Elementdeklaration ''{0}'' ist. '{'nillable'}' ist bei der Elementdeklaration ''true'', aber das entsprechende Partikel im Basistyp hat eine Elementdeklaration, bei der '{'nillable'}' ''false'' ist. - rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Fehler beim Partikel, dessen '{'term'}' die Elementdeklaration ''{0}'' ist. Der Vorkommensbereich ({1},{2}) ist keine g\u00FCltige Einschr\u00E4nkung des Bereichs ({3},{4}) des entsprechenden Partikels im Basistyp. + rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Fehler beim Partikel, dessen "{''term''}" die Elementdeklaration "{0}" ist. Der Vorkommensbereich ({1},{2}) ist keine g\u00FCltige Einschr\u00E4nkung des Bereichs ({3},{4}) des entsprechenden Partikels im Basistyp. rcase-NameAndTypeOK.4.a = rcase-NameAndTypeOK.4.a: Element ''{0}'' ist nicht fest, aber das entsprechende Element im Basistyp ist fest mit Wert ''{1}''. rcase-NameAndTypeOK.4.b = rcase-NameAndTypeOK.4.b: Element ''{0}'' ist fest mit dem Wert ''{1}'', aber das entsprechende Element im Basistyp ist fest mit Wert ''{2}''. rcase-NameAndTypeOK.5 = rcase-NameAndTypeOK.5: Identity Constraints f\u00FCr Element ''{0}'' sind keine Teilmenge der Constraints in der Basis. rcase-NameAndTypeOK.6 = rcase-NameAndTypeOK.6: Die unzul\u00E4ssigen Substitutionen f\u00FCr Element ''{0}'' sind keine Obermenge der Substitutionen in der Basis. rcase-NameAndTypeOK.7 = rcase-NameAndTypeOK.7: Typ des Elements ''{0}'' ''{1}'' wurde nicht vom Typ des Basiselements ''{2}'' abgeleitet. rcase-NSCompat.1 = rcase-NSCompat.1: Element ''{0}'' hat den Namespace ''{1}''. Dies wird vom Platzhalter in der Basis nicht zugelassen. - rcase-NSCompat.2 = rcase-NSCompat.2: Fehler beim Partikel, dessen '{'term'}' die Elementdeklaration ''{0}'' ist. Der Vorkommensbereich ({1},{2}) ist keine g\u00FCltige Einschr\u00E4nkung des Bereichs ({3},{4}) des entsprechenden Partikels im Basistyp. + rcase-NSCompat.2 = rcase-NSCompat.2: Fehler beim Partikel, dessen "{''term''}" die Elementdeklaration "{0}" ist. Der Vorkommensbereich ({1},{2}) ist keine g\u00FCltige Einschr\u00E4nkung des Bereichs ({3},{4}) des entsprechenden Partikels im Basistyp. rcase-NSRecurseCheckCardinality.1 = rcase-NSRecurseCheckCardinality.1: Es ist keine vollst\u00E4ndige Funktionszuordnung zwischen den Partikeln vorhanden. rcase-NSRecurseCheckCardinality.2 = rcase-NSRecurseCheckCardinality.2: Vorkommensbereich der Gruppe ({0},{1}) ist keine g\u00FCltige Einschr\u00E4nkung des Bereichs des Basisplatzhalters ({2},{3}). rcase-NSSubset.1 = rcase-NSSubset.1: Platzhalter ist keine Teilmenge des entsprechenden Platzhalters in der Basis. @@ -311,15 +285,15 @@ EmptyTargetNamespace = EmptyTargetNamespace: In Schemadokument ''{0}'' kann der Wert des ''targetNamespace''-Attributs keine leere Zeichenfolge sein. FacetValueFromBase = FacetValueFromBase: In der Deklaration von Typ ''{0}'' muss der Wert ''{1}'' von Facet ''{2}'' aus dem Wertebereich des Basistyps ''{3}'' stammen. FixedFacetValue = FixedFacetValue: In der Definition von {3} ist der Wert ''{1}'' f\u00FCr Facet ''{0}'' ung\u00FCltig, da der Wert f\u00FCr ''{0}'' in einem der Vorg\u00E4ngertypen auf ''{2}'' gesetzt wurde und ''{''fixed'}''' = true ist. - InvalidRegex = InvalidRegex: Musterwert ''{0}'' ist kein g\u00FCltiger regul\u00E4rer Ausdruck. Der gemeldete Fehler war: ''{1}'' bei Spalte ''{2}''. - MaxOccurLimit = Aktuelle Konfiguration des Parsers l\u00E4sst nicht zu, dass ein maxOccurs-Attributwert auf einen h\u00F6heren Wert als {0} gesetzt wird. + InvalidRegex = InvalidRegex: Musterwert "{0}" ist kein g\u00FCltiger regul\u00E4rer Ausdruck. Der gemeldete Fehler war: "{1}". + MaxOccurLimit = Aktuelle Konfiguration des Parsers l\u00E4sst nicht zu, dass ein Inhaltsmodell so erweitert wird, dass ein komplexer Typ mehr als {0} Knoten enth\u00E4lt. PublicSystemOnNotation = PublicSystemOnNotation: Mindestens eines der Elemente 'public' und 'system' muss im Element 'notation' vorkommen. SchemaLocation = SchemaLocation: schemaLocation-Wert = ''{0}'' muss eine gerade Anzahl an URIs haben. TargetNamespace.1 = TargetNamespace.1: Namespace ''{0}'' wird erwartet, aber der Ziel-Namespace des Schemadokuments ist ''{1}''. TargetNamespace.2 = TargetNamespace.2: Kein Namespace wird erwartet, aber das Schemadokument hat den Ziel-Namespace ''{1}''. UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' ist nicht deklariert. UndeclaredPrefix = UndeclaredPrefix: ''{0}'' kann nicht als QName aufgel\u00F6st werden: Pr\u00E4fix ''{1}'' ist nicht deklariert. - + FacetsContradict = FacetsContradict: F\u00FCr simpleType-Definition "{2}" widerspricht der Enumerationswert "{0}" dem Wert von Facet "{1}". # JAXP 1.2 schema source property errors diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties index b4d9ffafe78711a61ec24fba1014507f9d78606f..bcf6b336eb7aa4e39a6b07009c5a6d502d55a6e0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 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. 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. -# - # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties index 602d1314ac64df5bfc521c305c68a2d96bbda114..4e9a16dcb4f1c19633c2431095eb9ec06b9c7831 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 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. 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. -# - # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties index 3c1d9d8282cf29c7bdd836d6a19c4a934c21e306..c5b5cdbd949a21a52d0180448f739d4fcf2b5833 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties index 341497c9a6f3870380d5f07def46fe6775a8c709..b61a63b5b748314fc761b8dca05cddf7ea303319 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties index d8b2eb0bba5bec105a7c0ecdfd455cbe903ba5fc..4db14a65c4dd1a1bb9a82d768821a9ce322f6dc7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties index dc787a6cd3dc02a6e6de8415f624d6b883a85e41..3d33f7b86995ac6731587e93b71ead8d3247c21a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties index e12a67655f8f1ba4b2ac182581b2879e44121c0d..a93488316057c0538fb26e22be5c954827cdac29 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties index cbbaad08e7ba4703e7d0ae4436a06bf70a610dbe..bbf46c70eb7fe52c1eb86de91e20043349bf837e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_de.properties index 549f517840cb8d1336b5172bc659d833ee4a4257..816e86b09a8c2b4a39cd5d3d8b5def918d61c838 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_de.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - parser.parse.1=Falsches Zeichen. parser.parse.2=Ung\u00FCltige Referenznummer. parser.next.1=Nach \\ ist ein Zeichen erforderlich. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_ja.properties index fcc5ed576fb31d6219a5d0c37245ab4ad3fd1f37..09ffd559f5056102d9304c7258cd53d8f51040fb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_ja.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2013, 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. 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. -# - parser.parse.1=\u6587\u5B57\u304C\u9055\u3063\u3066\u3044\u307E\u3059\u3002 parser.parse.2=\u7121\u52B9\u306A\u53C2\u7167\u756A\u53F7\u3067\u3059\u3002 parser.next.1=\\\u306E\u5F8C\u306B\u6587\u5B57\u304C\u5FC5\u8981\u3067\u3059\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_zh_CN.properties index ee68bbdbcea5965693f2ce27aa877f739f7e0050..ab2e56846a9aeac3f8c41c551b7ec5b18f9dddf9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message_zh_CN.properties @@ -1,28 +1,3 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - parser.parse.1=\u5B57\u7B26\u9519\u8BEF\u3002 parser.parse.2=\u5F15\u7528\u53F7\u65E0\u6548\u3002 parser.next.1=\\ \u540E\u9762\u5FC5\u987B\u6709\u5B57\u7B26\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java index 46582fefd1b6f4bfc386d863640fef534bae2e78..fbb758def47166a5aa2d0bf671ddd58a792eebe2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2425,12 +2425,12 @@ public class XMLGregorianCalendarImpl if (lang != null) { if (country != null) { if (variant != null) { - locale = new Locale(lang, country, variant); + locale = Locale.of(lang, country, variant); } else { - locale = new Locale(lang, country); + locale = Locale.of(lang, country); } } else { - locale = new Locale(lang); + locale = Locale.of(lang); } } if (locale == null) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources_de.java index 5b85917759819384a578fbbd781ea088ed50604b..3c53ea089560645b5d1b5d1a71f3ea6f43b012dc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources_de.java @@ -286,7 +286,7 @@ public class XMLErrorResources_de extends ListResourceBundle "Ung\u00FCltige Portnummer"}, { ER_FRAG_FOR_GENERIC_URI, - "Fragment kann nur f\u00FCr einen generischen URI festgelegt werden"}, + "Fragment kann nur f\u00FCr eine generische URI festgelegt werden"}, { ER_FRAG_WHEN_PATH_NULL, "Fragment kann nicht festgelegt werden, wenn der Pfad null ist"}, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java index 93a4dd8d301f3726616266d0e3be1c588d7e5e37..126f5d152550b5b8a0f0089dd97a4266e44c7a6b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.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. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,6 +20,7 @@ package com.sun.org.apache.xml.internal.serializer; +import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xml.internal.serializer.dom3.DOMConstants; import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; import com.sun.org.apache.xml.internal.serializer.utils.Utils; @@ -54,7 +55,7 @@ import org.xml.sax.SAXException; * serializers (xml, html, text ...) that write output to a stream. * * @xsl.usage internal - * @LastModified: June 2021 + * @LastModified: Mar 2022 */ abstract public class ToStream extends SerializerBase { @@ -1745,13 +1746,19 @@ abstract public class ToStream extends SerializerBase { } else { - /* This if check is added to support control characters in XML 1.1. - * If a character is a Control Character within C0 and C1 range, it is desirable - * to write it out as Numeric Character Reference(NCR) regardless of XML Version - * being used for output document. + /* + * The check was added to support control characters in XML 1.1. + * It previously wrote Control Characters within C0 and C1 range + * as Numeric Character Reference(NCR) regardless of XML Version, + * which was incorrect as Control Characters are invalid in XML 1.0. */ - if (isCharacterInC0orC1Range(ch) || - (XMLVERSION11.equals(getVersion()) && isNELorLSEPCharacter(ch))) + boolean isVer11 = XMLVERSION11.equals(getVersion()); + if (!isVer11 && XMLChar.isInvalid(ch)) { + throw new org.xml.sax.SAXException(Utils.messages.createMessage( + MsgKey.ER_WF_INVALID_CHARACTER_IN_TEXT, + new Object[]{Integer.toHexString(ch)})); + } + if (isCharacterInC0orC1Range(ch) || (isVer11 && isNELorLSEPCharacter(ch))) { writeCharRef(writer, ch); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_de.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_de.java index bc444738f1af248b5003245f177f7019210697b1..1874693ccfeaf660d491f441098fe0d13bc48277 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_de.java @@ -162,7 +162,7 @@ public class SerializerMessages_de extends ListResourceBundle { "Fragment kann nicht festgelegt werden, wenn der Pfad null ist" }, { MsgKey.ER_FRAG_FOR_GENERIC_URI, - "Fragment kann nur f\u00FCr einen generischen URI festgelegt werden" }, + "Fragment kann nur f\u00FCr eine generische URI festgelegt werden" }, { MsgKey.ER_NO_SCHEME_IN_URI, "Kein Schema gefunden in URI" }, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/LocaleUtility.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/LocaleUtility.java index d63e26aafd45766fe26ff2e5b94d1582ca83b314..e08a619dd61f147c5621c56872e5eb47e238cf11 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/LocaleUtility.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/LocaleUtility.java @@ -78,7 +78,7 @@ public class LocaleUtility { variant = EMPTY_STRING; } - return new Locale(language, country, variant ); + return Locale.of(language, country, variant); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java index db9a3fdbc2e228f7581f34c27d55268ee48d95a3..7b3c5473e5e7002331ab9490a06949f755228f4d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -32,6 +31,7 @@ import java.util.ListResourceBundle; * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced + * @LastModified: Nov 2021 */ public class XPATHErrorResources_de extends ListResourceBundle { @@ -150,6 +150,10 @@ public class XPATHErrorResources_de extends ListResourceBundle "ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG"; public static final String ER_PREDICATE_ILLEGAL_SYNTAX = "ER_PREDICATE_ILLEGAL_SYNTAX"; + public static final String ER_PREDICATE_TOO_MANY_OPEN = + "ER_PREDICATE_TOO_MANY_OPEN"; + public static final String ER_COMPILATION_TOO_MANY_OPERATION = + "ER_COMPILATION_TOO_MANY_OPERATION"; public static final String ER_ILLEGAL_AXIS_NAME = "ER_ILLEGAL_AXIS_NAME"; public static final String ER_UNKNOWN_NODETYPE = "ER_UNKNOWN_NODETYPE"; public static final String ER_PATTERN_LITERAL_NEEDS_BE_QUOTED = @@ -318,6 +322,10 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE"; public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER"; public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER"; + public static final String ER_PROPERTY_NAME_NULL = "ER_PROPERTY_NAME_NULL"; + public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; + public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; + public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -435,7 +443,7 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = "ERROR. Unbekannter Vorgangscode: {0}"}, { ER_EXTRA_ILLEGAL_TOKENS, - "Zus\u00E4tzliche ung\u00FCltige Tokens: {0}"}, + "Zus\u00E4tzliche unzul\u00E4ssige Tokens: {0}"}, { ER_EXPECTED_DOUBLE_QUOTE, "Literal in falschen Anf\u00FChrungszeichen... Doppelte Anf\u00FChrungszeichen erwartet."}, @@ -462,10 +470,16 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = "\",\" gefunden, aber kein folgendes Argument vorhanden."}, { ER_PREDICATE_ILLEGAL_SYNTAX, - "\"..[predicate]\" oder \".[predicate]\" ist ung\u00FCltige Syntax. Verwenden Sie stattdessen \"self::node()[predicate]\"."}, + "\"..[predicate]\" oder \".[predicate]\" ist unzul\u00E4ssige Syntax. Verwenden Sie stattdessen \"self::node()[predicate]\"."}, + + { ER_PREDICATE_TOO_MANY_OPEN, + "Stack\u00FCberlauf beim Parsen von {0} bei {1}. Es sind zu viele offene Pr\u00E4dikate vorhanden ({2})."}, + + { ER_COMPILATION_TOO_MANY_OPERATION, + "Stack\u00FCberlauf beim Kompilieren des Ausdrucks. Es sind zu viele Vorg\u00E4nge vorhanden ({0})."}, { ER_ILLEGAL_AXIS_NAME, - "Ung\u00FCltiger Achsenname: {0}"}, + "Unzul\u00E4ssiger Achsenname: {0}"}, { ER_UNKNOWN_NODETYPE, "Unbekannter Knotentyp: {0}"}, @@ -826,6 +840,26 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = { ER_NULL_XPATH_VARIABLE_RESOLVER, "Versuch, Null-XPathVariableResolver festzulegen:{0}#setXPathVariableResolver(null)"}, + /** Field ER_PROPERTY_NAME_NULL */ + + { ER_PROPERTY_NAME_NULL, + "Es wird versucht, eine Eigenschaft mit einem Nullnamen festzulegen: {0}#setProperty(null, {1})"}, + + /** Field ER_PROPERTY_UNKNOWN */ + + { ER_PROPERTY_UNKNOWN, + "Es wird versucht, die unbekannte Eigenschaft \"{0}\" festzulegen: {1}#setProperty({0},{2})"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_NULL_PROPERTY, + "Es wird versucht, eine Eigenschaft mit einem Nullnamen abzurufen: {0}#getProperty(null)"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_UNKNOWN_PROPERTY, + "Es wird versucht, die unbekannte Eigenschaft \"{0}\" abzurufen: {1}#getProperty({0})"}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java index a8c681aaa373fda2495823071d4a1274fb4d8199..bdb2501b69abfca528b9b0c4bfa3bb89799ff82f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ import java.util.ListResourceBundle; * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: May 2019 + * @LastModified: Nov 2021 */ public class XPATHErrorResources_ja extends ListResourceBundle { @@ -322,6 +322,10 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE"; public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER"; public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER"; + public static final String ER_PROPERTY_NAME_NULL = "ER_PROPERTY_NAME_NULL"; + public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; + public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; + public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -836,6 +840,26 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = { ER_NULL_XPATH_VARIABLE_RESOLVER, "null\u306EXPathVariableResolver\u3092\u8A2D\u5B9A\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F: {0}#setXPathVariableResolver(null)"}, + /** Field ER_PROPERTY_NAME_NULL */ + + { ER_PROPERTY_NAME_NULL, + "\u30D7\u30ED\u30D1\u30C6\u30A3\u306Bnull\u306E\u540D\u524D\u3092\u8A2D\u5B9A\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F: {0}#setProperty( null, {1})"}, + + /** Field ER_PROPERTY_UNKNOWN */ + + { ER_PROPERTY_UNKNOWN, + "\u4E0D\u660E\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\"{0}\"\u3092\u8A2D\u5B9A\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F:{1}#setProperty({0},{2})"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_NULL_PROPERTY, + "null\u540D\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u53D6\u5F97\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F: {0}#getProperty(null)"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_UNKNOWN_PROPERTY, + "\u4E0D\u660E\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\"{0}\"\u3092\u53D6\u5F97\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F:{1}#getProperty({0})"}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java index d1e370f0d82c225bcede2c671b0850ed54139043..5c76b4c94718c6bff11be7f04326627fe3eedbee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ import java.util.ListResourceBundle; * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: May 2019 + * @LastModified: Nov 2021 */ public class XPATHErrorResources_zh_CN extends ListResourceBundle { @@ -322,6 +322,10 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE"; public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER"; public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER"; + public static final String ER_PROPERTY_NAME_NULL = "ER_PROPERTY_NAME_NULL"; + public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; + public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; + public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -836,6 +840,26 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED = { ER_NULL_XPATH_VARIABLE_RESOLVER, "\u5C1D\u8BD5\u8BBE\u7F6E\u7A7A XPathVariableResolver:{0}#setXPathVariableResolver(null)"}, + /** Field ER_PROPERTY_NAME_NULL */ + + { ER_PROPERTY_NAME_NULL, + "\u5C1D\u8BD5\u8BBE\u7F6E\u5177\u6709\u7A7A\u540D\u79F0\u7684\u5C5E\u6027\uFF1A{0}#setProperty( null, {1})"}, + + /** Field ER_PROPERTY_UNKNOWN */ + + { ER_PROPERTY_UNKNOWN, + "\u5C1D\u8BD5\u8BBE\u7F6E\u672A\u77E5\u5C5E\u6027 \"{0}\":{1}#setProperty({0},{2})"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_NULL_PROPERTY, + "\u5C1D\u8BD5\u83B7\u53D6\u5177\u6709\u7A7A\u540D\u79F0\u7684\u5C5E\u6027\uFF1A{0}#getProperty(null)"}, + + /** Field ER_GETTING_NULL_PROPERTY */ + + { ER_GETTING_UNKNOWN_PROPERTY, + "\u5C1D\u8BD5\u83B7\u53D6\u672A\u77E5\u5C5E\u6027 \"{0}\":{1}#getProperty({0})"}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... diff --git a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java index 92c407e103ff8fa2043489d56d4ef0b6e4ab9c8e..6bbbdc77b7dd42714e9a1e8f7999b9b8a6ab4dc3 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.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 @@ -28,10 +28,8 @@ import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; diff --git a/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java b/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java index 103078b15558b975a6aae7da130c61807b6c8a1a..1082f00450e16d5bdc9b15f7a0de2dfef2ca8c16 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java +++ b/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.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 @@ -40,6 +40,9 @@ class GroupEntry extends BaseEntry { static final int ATTRIBUTE_DEFFER = 1; static final int ATTRIBUTE_RESOLUTION = 2; + //Indicates a continuous session, should not reset state + boolean shouldKeepState = false; + //Unmodifiable features when the Catalog is created CatalogFeatures features; @@ -164,6 +167,16 @@ class GroupEntry extends BaseEntry { longestSuffixMatch = 0; systemEntrySearched = false; } + + /** + * Resets the state of the Catalog instance, allowing it to be reused. + */ + private void resetOnStart() { + if (this instanceof Catalog && !shouldKeepState) { + reset(); + } + } + /** * Constructs a group entry. * @param catalog the catalog this GroupEntry belongs to @@ -228,6 +241,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchSystem(String systemId) { + resetOnStart(); systemEntrySearched = true; String match = null; for (BaseEntry entry : entries) { @@ -296,6 +310,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchPublic(String publicId) { + resetOnStart(); /* When both public and system identifiers are specified, and prefer is not public (that is, system), only system entry will be used. @@ -326,6 +341,51 @@ class GroupEntry extends BaseEntry { return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId); } + /** + * Attempt to find a matching entry in the catalog by publicId or systemId. + * + *

    + * The resolution follows the following rules determined by the prefer + * setting: + * + * prefer "system": attempts to resolve with a system entry; attempts to + * resolve with a public entry when only publicId is specified. + * + * prefer "public": attempts to resolve with a system entry; attempts to + * resolve with a public entry if no matching system entry is found. + * + * If no match is found, continue searching uri entries. + * + * @param publicId The public identifier of the external entity being + * referenced. + * + * @param systemId The system identifier of the external entity being + * referenced. + * + * @return the resolved systemId if a match is found, null otherwise + */ + String resolve(String publicId, String systemId) { + String resolvedSystemId = null; + shouldKeepState = true; + if (systemId != null) { + /* + If a system identifier is specified, it is used no matter how + prefer is set. + */ + resolvedSystemId = matchSystem(systemId); + } + + if (resolvedSystemId == null && publicId != null) { + resolvedSystemId = matchPublic(publicId); + } + + if (resolvedSystemId == null && systemId != null) { + resolvedSystemId = matchURI(systemId); + } + shouldKeepState = false; + return resolvedSystemId; + } + /** * Attempt to find a matching entry in the catalog by the uri element. * @@ -340,6 +400,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchURI(String uri) { + resetOnStart(); String match = null; for (BaseEntry entry : entries) { switch (entry.type) { @@ -399,6 +460,7 @@ class GroupEntry extends BaseEntry { * @return the URI string if a mapping is found, or null otherwise. */ private String matchDelegate(CatalogEntryType type, String id) { + resetOnStart(); String match = null; int longestMatch = 0; URI catalogId = null; diff --git a/src/java.xml/share/classes/javax/xml/catalog/Util.java b/src/java.xml/share/classes/javax/xml/catalog/Util.java index af84c3f825df0b82b97b32925781c66d3b9c2db4..50a72aed6201607ec835bf96e4652e8d956de49c 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/Util.java +++ b/src/java.xml/share/classes/javax/xml/catalog/Util.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 @@ -74,25 +74,9 @@ class Util { * @return the resolved systemId if a match is found, null otherwise */ static String resolve(CatalogImpl catalog, String publicId, String systemId) { - String resolvedSystemId = null; - //search the current catalog catalog.reset(); - if (systemId != null) { - /* - If a system identifier is specified, it is used no matter how - prefer is set. - */ - resolvedSystemId = catalog.matchSystem(systemId); - } - - if (resolvedSystemId == null && publicId != null) { - resolvedSystemId = catalog.matchPublic(publicId); - } - - if (resolvedSystemId == null && systemId != null) { - resolvedSystemId = catalog.matchURI(systemId); - } + String resolvedSystemId = catalog.resolve(publicId, systemId); //mark the catalog as having been searched before trying alternatives catalog.markAsSearched(); diff --git a/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.java b/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.java index c5678b8b75061f3c1cd3569383f891919fd00986..760db484b97da0755767760829b1378a6ec6a24a 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.java +++ b/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.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 @@ -275,7 +275,7 @@ public class SecuritySupport { return ResourceBundle.getBundle(bundle, locale); } catch (MissingResourceException e) { try { - return ResourceBundle.getBundle(bundle, new Locale("en", "US")); + return ResourceBundle.getBundle(bundle, Locale.US); } catch (MissingResourceException e2) { throw new MissingResourceException( "Could not load any resource bundle by " + bundle, bundle, ""); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index 5cf8c5d5387f733eb2209ebc772fd6333721a88c..dbb4f1a46a4e08aa23ecbfd92a25d91c863c756c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -377,7 +377,7 @@ public class Enter extends JCTree.Visitor { ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge); c.flatname = names.fromString(tree.packge + "." + name); c.classfile = c.sourcefile = tree.sourcefile; - c.completer = Completer.NULL_COMPLETER; + c.completer = Completer.NULL_COMPLETER; c.members_field = WriteableScope.create(c); tree.packge.package_info = c; tree.packge.sourcefile = tree.sourcefile; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 0638da66a8969191b572a18375af6bee01790718..28662fe2dcc0667b64236aa13d3b88309b8bd970 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -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 @@ -2054,7 +2054,7 @@ public class LambdaToMethod extends TreeTranslator { }; break; case CAPTURED_OUTER_THIS: - Name name = names.fromString(new String(sym.flatName().toString().replace('.', '$') + names.dollarThis)); + Name name = names.fromString(sym.flatName().toString().replace('.', '$') + names.dollarThis); ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) { @Override public Symbol baseSymbol() { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java index bef291869ab36da185f5877c9ec044a480333e4e..1c3f8ba96f882cc7130c8523696c1cad7c002e8f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.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 @@ -54,7 +54,6 @@ import static javax.tools.StandardLocation.CLASS_OUTPUT; import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.ModuleSymbol; -import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.comp.Modules; import com.sun.tools.javac.model.JavacElements; @@ -63,10 +62,8 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; -import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.main.Option; -import java.util.stream.Collectors; /** * The FilerImplementation class must maintain a number of @@ -547,12 +544,11 @@ public class JavacFiler implements Filer, Closeable { locationCheck(location); - String strPkg = pkg.toString(); - if (strPkg.length() > 0) - checkName(strPkg); + if (pkg.length() > 0) + checkName(pkg); FileObject fileObject = - fileManager.getFileForOutputForOriginatingFiles(location, strPkg, + fileManager.getFileForOutputForOriginatingFiles(location, pkg, relativeName.toString(), originatingFiles(originatingElements)); checkFileReopening(fileObject, true); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 594bb4e95b4f7f4768a92f6517032328310fc07a..9174f0b7385dc098fd7c3cfb51d53d53040be025 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.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 @@ -300,10 +300,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea try { processorIterator = List.of(new PrintingProcessor()).iterator(); } catch (Throwable t) { - AssertionError assertError = - new AssertionError("Problem instantiating PrintingProcessor."); - assertError.initCause(t); - throw assertError; + throw new AssertionError("Problem instantiating PrintingProcessor.", t); } } else if (processors != null) { processorIterator = processors.iterator(); @@ -493,7 +490,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } private class NameServiceIterator extends ServiceIterator { - private Map namedProcessorsMap = new HashMap<>();; + private Map namedProcessorsMap = new HashMap<>(); private Iterator processorNames = null; private Processor nextProc = null; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index fddd3e935e1d24ca0fe321be4827dc47eb1040cd..0308f6a647e0b0dd0cbfb012fb4d5716da76882c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1565,9 +1565,6 @@ compiler.misc.diamond.anonymous.methods.implicitly.override=\ compiler.misc.source.unavailable=\ (source unavailable) -compiler.misc.base.membership=\ - all your base class are belong to us - # 0: string, 1: string, 2: boolean compiler.misc.x.print.processor.info=\ Processor {0} matches {1} and returns {2}. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..023f83aea3260583e7cac02d02a82e8f1891d5c4 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -0,0 +1,2785 @@ +# +# Copyright (c) 1999, 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. +# + +# Messages in this file which use "placeholders" for values (e.g. {0}, {1}) +# are preceded by a stylized comment describing the type of the corresponding +# values. +# The simple types currently in use are: +# +# annotation annotation compound +# boolean true or false +# diagnostic a sub-message; see compiler.misc.* +# fragment similar to 'message segment', but with more specific type +# modifier a Java modifier; e.g. public, private, protected +# file a file URL +# file object a file URL - similar to 'file' but typically used for source/class files, hence more specific +# flag a Flags.Flag instance +# name a name, typically a Java identifier +# number an integer +# option name the name of a command line option +# path a path +# profile a profile name +# source a source version number, such as 1.5, 1.6, 1.7, taken from a com.sun.tools.javac.code.Source +# source version a source version number, such as 1.5, 1.6, 1.7, taken from a javax.lang.model.SourceVersion +# string a general string +# symbol the name of a declared type +# symbol kind the kind of a symbol (i.e. method, variable) +# kind name an informative description of the kind of a declaration; see compiler.misc.kindname.* +# target a target version number, such as 1.5, 1.6, 1.7, taken from a com.sun.tools.javac.jvm.Target +# token the name of a non-terminal in source code; see compiler.misc.token.* +# tree tag the name of a non-terminal in source code; see compiler.misc.token.* +# type a Java type; e.g. int, X, X +# url a URL +# object a Java object (unspecified) +# unused the value is not used in this message +# +# The following compound types are also used: +# +# collection of X a comma-separated collection of items; e.g. collection of type +# list of X a comma-separated list of items; e.g. list of type +# set of X a comma-separated set of items; e.g. set of modifier +# +# These may be composed: +# +# list of type or message segment +# +# The following type aliases are supported: +# +# message segment --> diagnostic or fragment +# file name --> file, path or file object +# +# Custom comments are supported in parenthesis i.e. +# +# number (classfile major version) +# +# These comments are used internally in order to generate an enum-like class declaration containing +# a method/field for each of the diagnostic keys listed here. Those methods/fields can then be used +# by javac code to build diagnostics in a type-safe fashion. +# +# In addition, these comments are verified by the jtreg test test/tools/javac/diags/MessageInfo, +# using info derived from the collected set of examples in test/tools/javac/diags/examples. +# MessageInfo can also be run as a standalone utility providing more facilities +# for manipulating this file. For more details, see MessageInfo.java. + +## +## errors +## + +# 0: symbol +compiler.err.abstract.cant.be.instantiated={0} ist abstrakt, kann nicht instanziiert werden + +compiler.err.abstract.meth.cant.have.body=Abstrakte Methoden k\u00F6nnen keinen Body enthalten + +# 0: kind name, 1: symbol +compiler.err.already.annotated={0} {1} wurde bereits mit Annotation versehen + +# 0: kind name, 1: symbol, 2: kind name, 3: symbol +compiler.err.already.defined={0} {1} ist bereits in {2} {3} definiert + +# 0: kind name, 1: symbol, 2: kind name, 3: kind name, 4: symbol +compiler.err.already.defined.in.clinit={0} {1} ist bereits in {2} von {3} {4} definiert + +# 0: symbol +compiler.err.already.defined.single.import=Es wurde bereits ein Typ mit demselben einfachen Namen durch den Einzeltypimport von {0} definiert + +# 0: symbol +compiler.err.already.defined.static.single.import=Es wurde bereits ein Typ mit demselben einfachen Namen durch den statischen Einzeltypimport von {0} definiert + +# 0: symbol +compiler.err.already.defined.this.unit={0} ist in dieser Kompilierungseinheit bereits definiert + +# 0: type, 1: list of name +compiler.err.annotation.missing.default.value=In Annotation @{0} fehlt ein Standardwert f\u00FCr das Element "{1}" + +# 0: type, 1: list of name +compiler.err.annotation.missing.default.value.1=In Annotation @{0} fehlen Standardwerte f\u00FCr Elemente {1} + +# 0: type +compiler.err.annotation.not.valid.for.type=Annotation ist f\u00FCr Element des Typs {0} nicht g\u00FCltig + +compiler.err.annotation.type.not.applicable=Annotationsschnittstelle ist f\u00FCr diese Art Deklaration nicht anwendbar + +# 0: type +compiler.err.annotation.type.not.applicable.to.type=Annotation @{0} ist in diesem Typkontext nicht anwendbar + +compiler.err.annotation.value.must.be.annotation=Annotationswert muss eine Annotation sein + +compiler.err.annotation.value.must.be.class.literal=Annotationswert muss ein Klassenliteral sein + +compiler.err.annotation.value.must.be.name.value=Annotationswerte m\u00FCssen das Format "Name=Wert" aufweisen + +compiler.err.annotation.value.not.allowable.type=Annotationswert hat keinen zul\u00E4ssigen Typ + +compiler.err.expression.not.allowable.as.annotation.value=Ausdruck ist als Annotationswert nicht zul\u00E4ssig + +compiler.err.anon.class.impl.intf.no.args=Anonyme Klasse implementiert Schnittstelle. Argumente sind nicht m\u00F6glich + +compiler.err.anon.class.impl.intf.no.typeargs=Anonyme Klasse implementiert Schnittstelle. Typargumente sind nicht m\u00F6glich + +compiler.err.anon.class.impl.intf.no.qual.for.new=Anonyme Klasse implementiert Schnittstelle. Qualifier f\u00FCr "Neu" ist nicht m\u00F6glich + +compiler.err.cant.inherit.from.anon=Erben aus anonymer Klasse nicht m\u00F6glich + +# 0: symbol, 1: symbol, 2: symbol +compiler.err.array.and.varargs={0} und {1} k\u00F6nnen nicht beide in {2} deklariert werden + +compiler.err.array.dimension.missing=Arraydimension fehlt + +compiler.err.illegal.array.creation.both.dimension.and.initialization=Arrayerstellung mit Dimensionsausdruck und Initialisierung ist unzul\u00E4ssig + +# 0: type +compiler.err.array.req.but.found=Array erforderlich, aber {0} gefunden + +compiler.err.attribute.value.must.be.constant=Elementwert muss ein Konstantenausdruck sein + +# 0: string (statement type) +compiler.err.bad.initializer=Ung\u00FCltiger Initializer f\u00FCr {0} + +compiler.err.break.outside.switch.loop=Unterbrechung au\u00DFerhalb Switch oder Schleife + +compiler.err.break.outside.switch.expression=Versuch, Vorgang aus einem Switch-Ausdruck zu unterbrechen + +compiler.err.continue.outside.switch.expression=Versuch, Vorgang aus einem Switch-Ausdruck fortzusetzen + +compiler.err.return.outside.switch.expression=Versuch, aus einem Switch-Ausdruck zur\u00FCckzukehren + +compiler.err.rule.completes.normally=Switch-Regel wird ohne Angabe eines Wertes abgeschlossen\n(Switch-Regeln in Switch-Ausdr\u00FCcken m\u00FCssen einen Wert oder Throw angeben) + +compiler.err.switch.expression.completes.normally=Switch-Ausdruck wird ohne Angabe eines Wertes abgeschlossen\n(Switch-Ausdr\u00FCcke m\u00FCssen einen Wert angeben oder einen Throw f\u00FCr alle m\u00F6glichen Eingabewerte ausgeben) + +compiler.err.no.switch.expression ="yield" au\u00DFerhalb von Switch-Ausdruck + +compiler.err.no.switch.expression.qualify="yield" au\u00DFerhalb von Switch-Ausdruck\n(um eine Methode namens "yield" aufzurufen, qualifizieren Sie den yield-Aufruf mit einem Empf\u00E4nger oder Typnamen) + +compiler.err.invalid.yield=Ung\u00FCltige Verwendung der eingeschr\u00E4nkten ID "yield"\n(um eine Methode namens "yield" aufzurufen, qualifizieren Sie den yield-Aufruf mit einem Empf\u00E4nger oder Typnamen) + +compiler.warn.invalid.yield="yield" kann in einem zuk\u00FCnftigen Release zu einer eingeschr\u00E4nkten ID werden\n(um eine Methode namens "yield" aufzurufen, qualifizieren Sie den yield-Aufruf mit einem Empf\u00E4nger oder Typnamen) + +compiler.err.switch.expression.empty=Switch-Ausdruck enth\u00E4lt keine CASE-Klauseln + +compiler.err.switch.expression.no.result.expressions=Switch-Ausdruck enth\u00E4lt keine Ergebnisausdr\u00FCcke + +# 0: name +compiler.err.call.must.be.first.stmt.in.ctor=Aufruf von {0} muss die erste Anweisung im Konstruktor sein + +# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment +compiler.err.cant.apply.symbol={0} {1} in {4} {5} kann nicht auf die angegebenen Typen angewendet werden.\nErforderlich: {2}\nErmittelt: {3}\nGrund: {6} + +# 0: symbol kind, 1: name, 2: list of type +compiler.err.cant.apply.symbols={0} f\u00FCr {1}({2}) nicht geeignet + +# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment +compiler.misc.cant.apply.symbol={0} {1} in {4} {5} kann nicht auf die angegebenen Typen angewendet werden\nErforderlich: {2}\nErmittelt: {3}\nGrund: {6} + +# 0: symbol kind, 1: name, 2: list of type +compiler.misc.cant.apply.symbols={0} f\u00FCr {1}({2}) nicht geeignet + +# 0: kind name, 1: symbol +compiler.misc.no.abstracts=Keine abstrakte Methode in {0} {1} gefunden + +# 0: kind name, 1: symbol +compiler.misc.incompatible.abstracts=Mehrere nicht \u00FCberschreibende abstrakte Methoden in {0} {1} gefunden + +compiler.err.bad.functional.intf.anno=Unerwartete @FunctionalInterface-Annotation + +# 0: message segment +compiler.err.bad.functional.intf.anno.1=Unerwartete @FunctionalInterface-Annotation\n{0} + +# 0: message segment +compiler.err.anonymous.diamond.method.does.not.override.superclass=Methode \u00FCberschreibt oder implementiert keine Methode aus einem Supertyp\n{0} + +# 0: symbol +compiler.misc.not.a.functional.intf={0} ist keine Funktionsschnittstelle + +# 0: symbol, 1: message segment +compiler.misc.not.a.functional.intf.1={0} ist keine Funktionsschnittstelle\n{1} + +# 0: type, 1: kind name, 2: symbol +compiler.misc.invalid.generic.lambda.target=Ung\u00FCltiger Funktionsdeskriptor f\u00FCr Lambda-Ausdruck\nMethode {0} in {1} {2} ist generisch + +# 0: kind name, 1: symbol +compiler.misc.incompatible.descs.in.functional.intf=Inkompatible Funktionsdeskriptoren in {0} {1} gefunden + +# 0: name, 1: list of type, 2: type, 3: list of type +compiler.misc.descriptor=Deskriptor: {2} {0}({1}) + +# 0: name, 1: list of type, 2: type, 3: list of type +compiler.misc.descriptor.throws=Deskriptor: {2} {0}({1}) l\u00F6st {3} aus + +# 0: type +compiler.misc.no.suitable.functional.intf.inst=Funktionsschnittstellendeskriptor f\u00FCr {0} kann nicht abgeleitet werden + +# 0: message segment +compiler.misc.bad.intersection.target.for.functional.expr=Ung\u00FCltiges Schnittmengentypziel f\u00FCr Lambda oder Methodenreferenz\n{0} + +# 0: symbol or type +compiler.misc.not.an.intf.component=Komponententyp {0} ist keine Schnittstelle + +# 0: kind name, 1: message segment +compiler.err.invalid.mref=Ung\u00FCltige {0}-Referenz\n{1} + +# 0: kind name, 1: message segment +compiler.misc.invalid.mref=Ung\u00FCltige {0}-Referenz\n{1} + +compiler.misc.static.mref.with.targs=Parametrisierter Qualifier f\u00FCr statische Methodenreferenz + +# 0: symbol +compiler.err.cant.assign.val.to.final.var=Der finalen Variable {0} kann kein Wert zugewiesen werden + +compiler.err.cant.assign.val.to.this=Zuweisen zu "this" nicht m\u00F6glich + +# 0: symbol, 1: message segment +compiler.err.cant.ref.non.effectively.final.var=Von {1} referenzierte lokale Variablen m\u00FCssen final oder effektiv final sein + +compiler.err.try.with.resources.expr.needs.var=Die try-with-resources-Ressource muss eine Variablendeklaration oder ein Ausdruck mit einer Referenz zu einer finalen oder effektiv finalen Variable sein + +# 0: symbol +compiler.err.try.with.resources.expr.effectively.final.var=Variable {0}, die als try-with-resources-Ressource verwendet wurde, ist weder final noch effektiv final + + +compiler.misc.lambda=Lambda-Ausdruck + +compiler.misc.inner.cls=Innere Klasse + +compiler.misc.guard=Guard + +# 0: type +compiler.err.cant.deref={0} kann nicht dereferenziert werden + +compiler.err.cant.extend.intf.annotation="extends" f\u00FCr @interfaces nicht zul\u00E4ssig + +compiler.err.annotation.decl.not.allowed.here=Annotationsschnittstellendeklaration hier nicht zul\u00E4ssig + +# 0: symbol +compiler.err.cant.inherit.from.final=Erben aus finalem {0}-Element nicht m\u00F6glich + +# 0: symbol or string +compiler.err.cant.ref.before.ctor.called={0} kann nicht referenziert werden, bevor der Supertypkonstruktor aufgerufen wurde + +compiler.err.cant.select.static.class.from.param.type=Statische Klasse kann nicht aus einem parametrisierten Typ ausgew\u00E4hlt werden + +# 0: symbol, 1: string, 2: string +compiler.err.cant.inherit.diff.arg={0} kann nicht mit verschiedenen Argumenten geerbt werden: <{1}> und <{2}> + +compiler.err.catch.without.try="catch" ohne "try" + +# 0: kind name, 1: symbol +compiler.err.clash.with.pkg.of.same.name={0} {1} steht in Konflikt mit Package desselben Namens + +compiler.err.class.not.allowed=Klassen-, Schnittstellen- oder Enum-Deklaration hier nicht zul\u00E4ssig + +compiler.err.const.expr.req=Konstantenausdruck erforderlich + +compiler.err.cont.outside.loop=Fortsetzung au\u00DFerhalb Schleife + +# 0: symbol or type +compiler.err.cyclic.inheritance=Zyklische Vererbung mit {0} + +# 0: symbol +compiler.err.cyclic.annotation.element=Typ von Element {0} ist zyklisch + +# 0: symbol +compiler.err.call.to.super.not.allowed.in.enum.ctor=Aufruf von Super in Enum-Konstruktor nicht zul\u00E4ssig + +# 0: type +compiler.err.no.superclass={0} weist keine Superklasse auf. + +# 0: symbol, 1: type, 2: symbol, 3: type, 4: type +compiler.err.concrete.inheritance.conflict=Methoden {0} von {1} und {2} von {3} werden mit derselben Signatur geerbt + +compiler.err.default.allowed.in.intf.annotation.member=Standardwert nur in einer Annotationsschnittstellendeklaration zul\u00E4ssig + +# 0: symbol +compiler.err.doesnt.exist=Package {0} ist nicht vorhanden + +# 0: type +compiler.err.duplicate.annotation.invalid.repeated=Annotation {0} ist keine g\u00FCltige wiederholbare Annotation + +# 0: name, 1: type +compiler.err.duplicate.annotation.member.value=Doppeltes Element "{0}" in Annotation @{1}. + +# 0: type +compiler.err.duplicate.annotation.missing.container={0} ist keine wiederholbare Annotationsschnittstelle + +# 0: symbol +compiler.err.invalid.repeatable.annotation=Doppelte Annotation: {0} ist mit einer ung\u00FCltigen @Repeatable-Annotation versehen + +# 0: symbol or type +compiler.err.invalid.repeatable.annotation.no.value={0} ist keine g\u00FCltige @Repeatable-Annotation. Keine Wertelementmethode deklariert + +# 0: type, 1: number +compiler.err.invalid.repeatable.annotation.multiple.values={0} ist keine g\u00FCltige @Repeatable-Annotation. {1} Elementmethoden namens "value" deklariert + +# 0: type +compiler.err.invalid.repeatable.annotation.invalid.value={0} ist keine g\u00FCltige @Repeatable-Annotation. Ung\u00FCltiges Wertelement + +# 0: symbol or type, 1: type, 2: type +compiler.err.invalid.repeatable.annotation.value.return=\u00DCbergeordnete Annotationsschnittstelle ({0}) muss ein Element namens "value" mit dem Typ {2} deklarieren + +# 0: symbol or type, 1: symbol +compiler.err.invalid.repeatable.annotation.elem.nondefault=\u00DCbergeordnete Annotationsschnittstelle ({0}) enth\u00E4lt keinen Standardwert f\u00FCr Element {1} + +# 0: symbol, 1: string, 2: symbol, 3: string +compiler.err.invalid.repeatable.annotation.retention=Aufbewahrung der \u00FCbergeordneten Annotationsschnittstelle ({0}) ist k\u00FCrzer als die Aufbewahrung der wiederholbaren Annotationsschnittstelle ({2}) + +# 0: symbol, 1: symbol +compiler.err.invalid.repeatable.annotation.not.documented=Wiederholbare Annotationsschnittstelle ({1}) ist @Documented, die \u00FCbergeordnete Annotationsschnittstelle ({0}) aber nicht + +# 0: symbol, 1: symbol +compiler.err.invalid.repeatable.annotation.not.inherited=Wiederholbare Annotationsschnittstelle ({1}) ist @Inherited, die \u00FCbergeordnete Annotationsschnittstelle ({0}) aber nicht + +# 0: symbol, 1: symbol +compiler.err.invalid.repeatable.annotation.incompatible.target=\u00DCbergeordnete Annotationsschnittstelle ({0}) gilt f\u00FCr mehr Ziele als die wiederholbare Annotationsschnittstelle ({1}) + +# 0: symbol +compiler.err.invalid.repeatable.annotation.repeated.and.container.present=Container {0} darf nicht gleichzeitig mit dem darin enthaltenen Element vorhanden sein + +# 0: type, 1: symbol +compiler.err.invalid.repeatable.annotation.not.applicable=Container {0} ist nicht anwendbar f\u00FCr Element {1} + +# 0: type +compiler.err.invalid.repeatable.annotation.not.applicable.in.context=Container {0} ist in diesem Typkontext nicht anwendbar + +# 0: name +compiler.err.duplicate.class=Doppelte Klasse: {0} + +# 0: name, 1: name +compiler.err.same.binary.name=Klassen {0} und {1} haben denselben bin\u00E4ren Namen + +compiler.err.duplicate.case.label=Doppeltes CASE-Label + +compiler.err.pattern.dominated=Dieses CASE-Label wird von einem vorherigen CASE-Label dominiert + +compiler.err.duplicate.default.label=Doppeltes Standardlabel + +compiler.err.duplicate.total.pattern=Doppeltes Gesamtmuster + +compiler.err.total.pattern.and.default=Switch umfasst sowohl Gesamtmuster als auch Standardlabel + +# 0: type, 1: type +compiler.err.constant.label.not.compatible=Konstantes Label des Typs {0} ist nicht mit Switch-Selektortyp {1} kompatibel + +compiler.err.flows.through.to.pattern=Ung\u00FCltiger Fallthrough zu einem Muster + +compiler.err.flows.through.from.pattern=Ung\u00FCltiger Fallthrough von einem Muster + +compiler.err.else.without.if="else" ohne "if" + +compiler.err.empty.char.lit=Leeres Zeichenliteral + +# 0: symbol +compiler.err.encl.class.required=Eine einschlie\u00DFende Instanz mit {0} ist erforderlich + +compiler.err.enum.annotation.must.be.enum.constant=Ein Enum-Annotationswert muss eine Enum-Konstante sein + +compiler.err.enum.cant.be.instantiated=Enum-Klassen d\u00FCrfen nicht instanziiert werden + +compiler.err.enum.label.must.be.unqualified.enum=Das CASE-Label eines Enum-Switches muss der unqualifizierte Name einer Enumerationskonstante sein + +compiler.err.enum.no.subclassing=Klassen k\u00F6nnen java.lang.Enum nicht direkt erweitern + +compiler.err.enum.types.not.extensible=Enum-Klassen sind nicht erweiterbar + +compiler.err.enum.no.finalize=Enums k\u00F6nnen keine Finalisierungsmethoden aufweisen + +# 0: file name, 1: string +compiler.err.error.reading.file=Fehler beim Lesen von {0}. {1} + +# 0: type +compiler.err.except.already.caught=Ausnahme {0} wurde bereits abgefangen + +# 0: type +compiler.err.except.never.thrown.in.try=Ausnahme {0} wird nie im Body der entsprechenden try-Anweisung ausgel\u00F6st + +# 0: symbol +compiler.err.final.parameter.may.not.be.assigned=final-Parameter {0} darf nicht zugewiesen werden + +# 0: symbol +compiler.err.try.resource.may.not.be.assigned=auto-closeable-Ressource {0} darf nicht zugewiesen werden + +# 0: symbol +compiler.err.multicatch.parameter.may.not.be.assigned=multi-catch-Parameter {0} darf nicht zugewiesen werden + +# 0: type, 1: type +compiler.err.multicatch.types.must.be.disjoint=Alternativen in einer multi-catch-Anweisung d\u00FCrfen nicht durch Unterklassen verkn\u00FCpft sein\nAlternative {0} ist eine Unterklasse der Alternative {1} + +compiler.err.finally.without.try="finally" ohne "try" + +# 0: type, 1: message segment +compiler.err.foreach.not.applicable.to.type=for-each nicht auf Ausdruckstyp anwendbar\nErforderlich: {1}\nErmittelt: {0} + +compiler.err.fp.number.too.large=Gleitkommazahl zu gro\u00DF + +compiler.err.fp.number.too.small=Gleitkommazahl zu klein + +compiler.err.generic.array.creation=Erstellung von generischem Array + +compiler.err.generic.throwable=Eine generische Klasse darf java.lang.Throwable nicht erweitern + +# 0: symbol +compiler.err.icls.cant.have.static.decl=Unzul\u00E4ssige static-Deklaration in innerer Klasse {0}\nModifikator "static" ist nur in Konstantenvariablendeklarationen zul\u00E4ssig + +# 0: string +compiler.err.illegal.char=Unzul\u00E4ssiges Zeichen: "{0}" + +# 0: string, 1: string +compiler.err.illegal.char.for.encoding=Nicht zuordenbares Zeichen (0x{0}) f\u00FCr Codierung {1} + +# 0: set of flag, 1: set of flag +compiler.err.illegal.combination.of.modifiers=Unzul\u00E4ssige Kombination aus Modifikatoren: {0} und {1} + +compiler.err.illegal.enum.static.ref=Unzul\u00E4ssige Referenz zu statischem Feld aus Initializer + +compiler.err.illegal.esc.char=Unzul\u00E4ssiges Escapezeichen + +compiler.err.illegal.forward.ref=Unzul\u00E4ssige Vorw\u00E4rtsreferenz + +# 0: symbol, 1: object +compiler.err.not.in.profile={0} ist in Profil "{1}" nicht verf\u00FCgbar + +# 0: symbol +compiler.warn.forward.ref=Referenz zu Variable "{0}", bevor sie initialisiert wurde + +compiler.err.illegal.self.ref=Selbstreferenz in Initializer + +# 0: symbol +compiler.warn.self.ref=Selbstreferenz in Initializer von Variable "{0}" + +# 0: type +compiler.err.illegal.initializer.for.type=Unzul\u00E4ssiger Initializer f\u00FCr {0} + +compiler.err.illegal.line.end.in.char.lit=Unzul\u00E4ssiges Zeilenende in Zeichenliteral + +compiler.err.illegal.text.block.open=Unzul\u00E4ssige Sequenz f\u00FCr \u00D6ffnungstrennzeichen von Textblock. Zeilenabschlusszeichen fehlt + +compiler.warn.inconsistent.white.space.indentation=Inkonsistenter Leerzeicheneinzug + +compiler.warn.trailing.white.space.will.be.removed=Nachgestelltes Leerzeichen wird entfernt + +compiler.err.illegal.nonascii.digit=Unzul\u00E4ssige Nicht-ASCII-Ziffer + +compiler.err.illegal.underscore=Unzul\u00E4ssiger Unterstrich + +compiler.err.illegal.dot="." unzul\u00E4ssig + +# 0: symbol +compiler.err.illegal.qual.not.icls=Unzul\u00E4ssiger Qualifier. {0} ist keine innere Klasse + +compiler.err.illegal.start.of.expr=Unzul\u00E4ssiger Ausdrucksbeginn + +compiler.err.illegal.start.of.stmt=Unzul\u00E4ssiger Anweisungsbeginn + +compiler.err.illegal.start.of.type=Unzul\u00E4ssiger Typbeginn + +compiler.err.illegal.parenthesized.expression=Unzul\u00E4ssiger Ausdruck in Klammern + +compiler.err.illegal.unicode.esc=Unzul\u00E4ssiges Unicode-Escapezeichen + +# 0: symbol +compiler.err.import.requires.canonical=Import erfordert kanonischen Namen f\u00FCr {0} + +compiler.err.improperly.formed.type.param.missing=Falsch formatierter Typ. Einige Parameter fehlen + +compiler.err.improperly.formed.type.inner.raw.param=Falsch formatierter Typ. Typargumente f\u00FCr Raw-Typ angegeben + +# 0: type, 1: type +compiler.err.incomparable.types=Nicht vergleichbare Typen: {0} und {1} + +# 0: string +compiler.err.int.number.too.large=Ganzzahl zu gro\u00DF + +compiler.err.intf.annotation.members.cant.have.params=Elemente in Annotationsschnittstellendeklarationen k\u00F6nnen keine formalen Parameter deklarieren + +# 0: symbol +compiler.err.intf.annotation.cant.have.type.params=Annotationsschnittstelle {0} darf nicht generisch sein + +compiler.err.intf.annotation.members.cant.have.type.params=Elemente in Annotationsschnittstellendeklarationen k\u00F6nnen keine generischen Methoden sein + +# 0: symbol, 1: type +compiler.err.intf.annotation.member.clash=Annotationsschnittstelle {1} deklariert ein Element mit demselben Namen wie Methode {0} + +compiler.err.intf.expected.here=Hier wird eine Schnittstelle erwartet + +compiler.err.intf.meth.cant.have.body=Abstrakte Schnittstellenmethoden k\u00F6nnen keinen Body enthalten + +compiler.err.invalid.annotation.member.type=Ung\u00FCltiger Typ f\u00FCr Annotationsschnittstellenelement + +compiler.err.invalid.binary.number=Bin\u00E4rzahlen m\u00FCssen mindestens eine Bin\u00E4rziffer enthalten + +compiler.err.invalid.hex.number=Hexadezimalzahlen m\u00FCssen mindestens eine Hexadezimalziffer enthalten + +compiler.err.invalid.meth.decl.ret.type.req=Ung\u00FCltige Methodendeklaration. R\u00FCckgabetyp erforderlich + +compiler.err.varargs.and.old.array.syntax=Legacy-Arraynotation f\u00FCr Parameter mit variabler Argumentanzahl nicht zul\u00E4ssig + +compiler.err.varargs.and.receiver =varargs-Notation f\u00FCr receiver-Parameter nicht zul\u00E4ssig + +compiler.err.varargs.must.be.last =varargs-Parameter muss der letzte Parameter sein + +compiler.err.array.and.receiver =Legacy-Arraynotation f\u00FCr receiver-Parameter nicht zul\u00E4ssig + +compiler.err.wrong.receiver =Falscher receiver-Parametername + +compiler.err.variable.not.allowed=Variablendeklaration hier nicht zul\u00E4ssig + +# 0: name +compiler.err.label.already.in.use=Label {0} wird bereits verwendet + +# 0: symbol +compiler.err.local.var.accessed.from.icls.needs.final=Auf lokale Variable {0} wird von innerer Klasse zugegriffen. Sie muss als final deklariert werden + +compiler.err.local.enum=Enum-Klassen d\u00FCrfen nicht lokal sein + +compiler.err.cannot.create.array.with.type.arguments=Array kann nicht mit Typargumenten erstellt werden + +compiler.err.cannot.create.array.with.diamond=Array kann nicht mit "<>" erstellt werden + +compiler.err.invalid.module.directive=Moduldirektiven-Schl\u00FCsselwort oder "}" erwartet + +# +# limits. We don't give the limits in the diagnostic because we expect +# them to change, yet we want to use the same diagnostic. These are all +# detected during code generation. +# +compiler.err.limit.code=Code zu gro\u00DF + +compiler.err.limit.code.too.large.for.try.stmt=Code f\u00FCr try-Anweisung zu gro\u00DF + +compiler.err.limit.dimensions=Arraytyp hat zu viele Dimensionen + +compiler.err.limit.locals=Zu viele lokale Variablen + +compiler.err.limit.parameters=Zu viele Parameter + +compiler.err.limit.pool=Zu viele Konstanten + +compiler.err.limit.pool.in.class=Zu viele Konstanten in Klasse {0} + +compiler.err.limit.stack=Code erfordert zu viel Stack + +compiler.err.limit.string=Konstantenzeichenfolge zu lang + +# 0: string +compiler.err.limit.string.overflow=UTF8-Darstellung f\u00FCr Zeichenfolge "{0}..." ist zu lang f\u00FCr den Konstantenpool + +compiler.err.malformed.fp.lit=Nicht wohlgeformtes Gleitkommaliteral + +compiler.err.method.does.not.override.superclass=Methode \u00FCberschreibt oder implementiert keine Methode aus einem Supertyp + +compiler.err.static.methods.cannot.be.annotated.with.override=Statische Methoden k\u00F6nnen nicht mit @Override-Annotation versehen werden + +compiler.err.missing.meth.body.or.decl.abstract=Methodenbody fehlt oder als abstrakt deklarieren + +compiler.err.missing.ret.stmt=R\u00FCckgabeanweisung fehlt + +# 0: type +compiler.misc.missing.ret.val=R\u00FCckgabewert fehlt + +compiler.misc.unexpected.ret.val=Unerwarteter R\u00FCckgabewert + +# 0: set of flag +compiler.err.mod.not.allowed.here=Modifikator {0} hier nicht zul\u00E4ssig + +# 0: name +compiler.err.modifier.not.allowed.here=Modifikator {0} hier nicht zul\u00E4ssig + +compiler.err.intf.not.allowed.here=Schnittstelle hier nicht zul\u00E4ssig + +# 0: symbol, 1: symbol +compiler.err.name.clash.same.erasure=Namenskonflikt: {0} und {1} haben dieselbe Erasure + +# 0: name, 1: list of type, 2: symbol, 3: name, 4: list of type, 5: symbol +compiler.err.name.clash.same.erasure.no.override=Namenskonflikt: {0}({1}) in {2} und {3}({4}) in {5} haben dieselbe Erasure, aber keine setzt die andere au\u00DFer Kraft + +# 0: string, 1: name, 2: name, 3: list of type, 4: symbol, 5: name, 6: list of type, 7: symbol +compiler.err.name.clash.same.erasure.no.override.1=Namenskonflikt: {0} {1} hat zwei Methoden mit derselben Erasure, aber keine setzt die andere au\u00DFer Kraft\nErste Methode: {2}({3}) in {4}\nZweite Methode: {5}({6}) in {7} + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.err.name.clash.same.erasure.no.hide=Namenskonflikt: {0} in {1} und {2} in {3} haben dieselbe Erasure, aber keine blendet die andere aus + +compiler.err.name.reserved.for.internal.use={0} ist f\u00FCr den internen Gebrauch reserviert + +compiler.err.native.meth.cant.have.body=Native Methoden k\u00F6nnen keinen Body enthalten + + +# 0: message segment +compiler.misc.incompatible.type.in.conditional=Ung\u00FCltiger Typ in Bedingungsausdruck\n{0} + +compiler.misc.conditional.target.cant.be.void=target-type f\u00FCr Bedingungsausdruck darf nicht "void" sein + +compiler.misc.switch.expression.target.cant.be.void=target-type f\u00FCr Switch-Ausdruck darf nicht "void" sein + +# 0: message segment +compiler.misc.incompatible.type.in.switch.expression=Ung\u00FCltiger Typ in Switch-Ausdruck\n{0} + +# 0: message segment +compiler.misc.incompatible.ret.type.in.lambda=Ung\u00FCltiger R\u00FCckgabetyp in Lambda-Ausdruck\n{0} + +compiler.misc.stat.expr.expected=Lambda-Body ist nicht mit einer void-Funktionsschnittstelle kompatibel\n(verwenden Sie stattdessen einen Block-Lambda-Body oder einen Anweisungsausdruck) + +# 0: message segment +compiler.misc.incompatible.ret.type.in.mref=Ung\u00FCltiger R\u00FCckgabetyp in Methodenreferenz\n{0} + +compiler.err.lambda.body.neither.value.nor.void.compatible=Lambda-Body ist weder mit Wert noch mit "void "kompatibel + +# 0: list of type +compiler.err.incompatible.thrown.types.in.mref=Inkompatible ausgel\u00F6ste Typen {0} in Funktionsausdruck + +compiler.misc.incompatible.arg.types.in.lambda=Inkompatible Parametertypen in Lambda-Ausdruck + +compiler.misc.incompatible.arg.types.in.mref=Inkompatible Parametertypen in Methodenreferenz + +compiler.err.new.not.allowed.in.annotation="new" in einer Annotation nicht zul\u00E4ssig + +# 0: name, 1: type +compiler.err.no.annotation.member=Kein Annotationsmitglied {0} in {1} + +# 0: symbol +compiler.err.no.encl.instance.of.type.in.scope=Keine einschlie\u00DFende Instanz vom Typ {0} im Geltungsbereich + +compiler.err.no.intf.expected.here=Hier wird keine Schnittstelle erwartet + +compiler.err.no.match.entry={0} hat keine \u00DCbereinstimmung im Eintrag in {1}. {2} erforderlich + +# 0: type +compiler.err.not.annotation.type={0} ist keine Annotationsschnittstelle + +# 0: symbol, 1: symbol, 2: message segment +compiler.err.not.def.access.package.cant.access={0} ist nicht sichtbar\n({2}) + +# 0: symbol, 1: symbol, 2: message segment +compiler.misc.not.def.access.package.cant.access={0} ist nicht sichtbar\n({2}) + +# 0: symbol, 1: message segment +compiler.err.package.not.visible=Package {0} ist nicht sichtbar\n({1}) + +# 0: symbol, 1: message segment +compiler.misc.package.not.visible=Package {0} ist nicht sichtbar\n({1}) + +# {0} - current module +# {1} - package in which the invisible class is declared +# {2} - module in which {1} is declared +# 0: symbol, 1: symbol, 2: symbol +compiler.misc.not.def.access.does.not.read=Package {1} wird in Modul {2} deklariert, aber nicht von Modul {0} gelesen + +# {0} - package in which the invisible class is declared +# {1} - module in which {0} is declared +# 0: symbol, 1: symbol +compiler.misc.not.def.access.does.not.read.from.unnamed=Package {0} wird in Modul {1} deklariert, das nicht im Moduldiagramm enthalten ist + +# {0} - package in which the invisible class is declared +# {1} - current module +# 0: symbol, 1: symbol +compiler.misc.not.def.access.does.not.read.unnamed=Package {0} wird im unbenannten Modul deklariert, aber nicht von Modul {1} gelesen + +# {0} - package in which the invisible class is declared +# {1} - module in which {0} is declared +# 0: symbol, 1: symbol +compiler.misc.not.def.access.not.exported=Package {0} wird in Modul {1} deklariert, aber nicht exportiert + +# {0} - package in which the invisible class is declared +# {1} - module in which {0} is declared +# 0: symbol, 1: symbol +compiler.misc.not.def.access.not.exported.from.unnamed=Package {0} wird in Modul {1} deklariert, aber nicht exportiert + +# {0} - package in which the invisible class is declared +# {1} - module in which {0} is declared +# {2} - current module +# 0: symbol, 1: symbol, 2: symbol +compiler.misc.not.def.access.not.exported.to.module=Package {0} wird in Modul {1} deklariert, aber nicht in Modul {2} exportiert + +# {0} - package in which the invisible class is declared +# {1} - module in which {0} is declared +# 0: symbol, 1: symbol +compiler.misc.not.def.access.not.exported.to.module.from.unnamed=Package {0} wird in Modul {1} deklariert, aber nicht in das unbenannte Modul exportiert + +# 0: symbol, 1: symbol +compiler.err.not.def.access.class.intf.cant.access={1}.{0} ist in einer nicht zug\u00E4nglichen Klasse oder Schnittstelle definiert + +# 0: symbol, 1: symbol +compiler.misc.not.def.access.class.intf.cant.access={1}.{0} ist in einer nicht zug\u00E4nglichen Klasse oder Schnittstelle definiert + +# 0: symbol, 1: symbol, 2: symbol, 3: message segment +compiler.err.not.def.access.class.intf.cant.access.reason={1}.{0} in Package {2} ist nicht zug\u00E4nglich\n({3}) + +# 0: symbol, 1: symbol, 2: symbol, 3: message segment +compiler.misc.not.def.access.class.intf.cant.access.reason={1}.{0} in Package {2} ist nicht zug\u00E4nglich\n({3}) + +# 0: symbol, 1: list of type, 2: type +compiler.misc.cant.access.inner.cls.constr=Zugriff auf Konstruktor {0}({1}) nicht m\u00F6glich\nEinschlie\u00DFende Instanz vom Typ {2} ist nicht im Geltungsbereich + +# 0: symbol, 1: symbol +compiler.err.not.def.public.cant.access={0} ist nicht \u00F6ffentlich in {1}. Zugriff von externem Package nicht m\u00F6glich + +# 0: symbol, 1: symbol +compiler.err.not.def.public={0} ist nicht \u00F6ffentlich in {1} + +# 0: symbol, 1: symbol +compiler.misc.not.def.public.cant.access={0} ist nicht \u00F6ffentlich in {1}. Zugriff von externem Package nicht m\u00F6glich + +# 0: name +compiler.err.not.loop.label=Kein Schleifenlabel: {0} + +compiler.err.not.stmt=Keine Anweisung + +# 0: symbol +compiler.err.not.encl.class=Keine einschlie\u00DFende Klasse: {0} + +# 0: name, 1: type +compiler.err.operator.cant.be.applied=Ung\u00FCltiger Operandentyp {1} f\u00FCr un\u00E4ren Operator "{0}" + +# 0: name, 1: type, 2: type +compiler.err.operator.cant.be.applied.1=Ung\u00FCltige Operandentypen f\u00FCr un\u00E4ren Operator "{0}"\nErster Typ: {1}\nZweiter Typ: {2} + +compiler.err.pkg.annotations.sb.in.package-info.java=Packageannotationen m\u00FCssen in der Datei package-info.java vorhanden sein + +compiler.err.no.pkg.in.module-info.java=Packagedeklarationen in Datei module-info.java nicht zul\u00E4ssig + +# 0: symbol +compiler.err.pkg.clashes.with.class.of.same.name=Es besteht ein Konflikt zwischen dem Package {0} und einer gleichnamigen Klasse + +compiler.err.warnings.and.werror=Warnungen gefunden und -Werror angegeben + +# Errors related to annotation processing + +# 0: symbol, 1: message segment, 2: string (stack-trace) +compiler.err.proc.cant.access=Kein Zugriff auf {0}\n{1}\nDetails finden Sie im folgenden Stacktrace.\n{2} + +# 0: symbol, 1: message segment +compiler.err.proc.cant.access.1=Kein Zugriff auf {0}\n{1} + +# 0: string +compiler.err.proc.cant.find.class=Klassendatei f\u00FCr "{0}" konnte nicht gefunden werden. + +# 0: string +compiler.err.proc.cant.load.class=Prozessorklassendatei konnte nicht geladen werden. Grund: "{0}". + +# Print a client-generated error message; assumed to be localized, no translation required +# 0: string +compiler.err.proc.messager={0} + +# 0: string +compiler.misc.exception.message={0} + +compiler.misc.user.selected.completion.failure=Von Benutzer ausgew\u00E4hlter Abschlussfehler nach Klassenname + +# 0: collection of string +compiler.err.proc.no.explicit.annotation.processing.requested=Klassennamen "{0}" werden nur akzeptiert, wenn die Annotationsverarbeitung explizit angefordert wird + +compiler.err.proc.no.service=ServiceLoader konnte nicht verwendet werden und ist f\u00FCr Annotationsverarbeitung erforderlich. + +# 0: string, 1: string +compiler.err.proc.processor.bad.option.name=Ung\u00FCltiger Optionsname "{0}" von Prozessor "{1}" angegeben + +# 0: string +compiler.err.proc.processor.cant.instantiate=Instanz von Prozessor "{0}" konnte nicht instanziiert werden + +# 0: string +compiler.err.proc.processor.not.found=Annotationsprozessor "{0}" nicht gefunden + +# 0: string +compiler.err.proc.processor.wrong.type=Annotationsprozessor "{0}" implementiert nicht javax.annotation.processing.Processor + +compiler.err.proc.service.problem=Fehler beim Erstellen eines Service-Loaders zum Laden von Prozessoren. + +# 0: string +compiler.err.proc.bad.config.file=Ung\u00FCltige Servicekonfigurationsdatei, oder Ausnahme beim Erstellen des Prozessorobjekts ausgel\u00F6st: {0} + +compiler.err.proc.cant.create.loader=Class Loader konnte nicht f\u00FCr Annotationsprozessoren erstellt werden: {0} + +# 0: symbol +compiler.err.qualified.new.of.static.class="new" von statischer Klasse qualifiziert + +compiler.err.recursive.ctor.invocation=Rekursiver Konstruktoraufruf + +# 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol +compiler.err.ref.ambiguous=Referenz zu {0} ist mehrdeutig\nSowohl {1} {2} in {3} als auch {4} {5} in {6} stimmen \u00FCberein + +# 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol +compiler.misc.ref.ambiguous=Referenz zu {0} ist mehrdeutig\nSowohl {1} {2} in {3} als auch {4} {5} in {6} stimmen \u00FCberein + +compiler.err.repeated.annotation.target=Wiederholtes Annotationsziel + +compiler.err.repeated.interface=Wiederholte Schnittstelle + +compiler.err.repeated.modifier=Wiederholter Modifikator + +# 0: symbol, 1: set of modifier, 2: symbol +compiler.err.report.access={0} hat {1}-Zugriff in {2} + +# 0: symbol, 1: set of modifier, 2: symbol +compiler.misc.report.access={0} hat {1}-Zugriff in {2} + +compiler.err.ret.outside.meth=R\u00FCckgabe au\u00DFerhalb von Methode + +compiler.err.signature.doesnt.match.supertype=Signatur stimmt nicht mit {0} \u00FCberein. Inkompatibler Supertyp + +compiler.err.signature.doesnt.match.intf=Signatur stimmt nicht mit {0} \u00FCberein. Inkompatible Schnittstellen + +# 0: symbol, 1: symbol, 2: symbol +compiler.err.does.not.override.abstract={0} ist nicht abstrakt und setzt die abstrakte Methode {1} in {2} nicht au\u00DFer Kraft + +# 0: file object +compiler.err.source.cant.overwrite.input.file=Fehler beim Schreiben von Quelle. Eingabedatei {0} kann nicht \u00FCberschrieben werden + +# 0: symbol +compiler.err.stack.sim.error=Interner Fehler: Stacksimulationsfehler in {0} + +compiler.err.static.imp.only.classes.and.interfaces=Statischer Import nur aus Klassen und Schnittstellen + +compiler.err.string.const.req=Konstanten-Zeichenfolgenausdruck erforderlich + +compiler.err.pattern.expected=Typmuster erwartet + +# 0: symbol, 1: fragment +compiler.err.cannot.generate.class=Fehler beim Generieren der Klasse {0}\n({1}) + +# 0: symbol, 1: symbol +compiler.misc.synthetic.name.conflict=Das Symbol {0} steht mit einem vom Compiler synthetisierten Symbol in {1} in Konflikt + +# 0: symbol, 1: type +compiler.misc.illegal.signature=Unzul\u00E4ssiges Signaturattribut f\u00FCr Typ {1} + +compiler.err.throws.not.allowed.in.intf.annotation=Throws-Klausel in @interface-Mitgliedern nicht zul\u00E4ssig + +compiler.err.try.without.catch.finally.or.resource.decls="try" ohne "catch", "finally" oder Ressourcendeklarationen + +# 0: symbol +compiler.err.type.doesnt.take.params=Typ {0} akzeptiert keine Parameter + +compiler.err.type.var.cant.be.deref=Auswahl aus Typvariable nicht m\u00F6glich + +compiler.err.type.var.may.not.be.followed.by.other.bounds=Auf eine Typvariable d\u00FCrfen keine anderen Begrenzungen folgen + +compiler.err.type.var.more.than.once=Typvariable {0} tritt mehrmals im Ergebnistyp von {1} auf. Sie muss instanziiert werden + +compiler.err.type.var.more.than.once.in.result=Typvariable {0} tritt mehrmals im Typ von {1} auf. Sie muss instanziiert werden + +# 0: type, 1: type, 2: fragment +compiler.err.types.incompatible=Die Typen {0} und {1} sind inkompatibel.\n{2} + +# 0: name, 1: list of type +compiler.misc.incompatible.diff.ret=Beide definieren {0}({1}), aber mit nicht verwandten R\u00FCckgabetypen + +# 0: kind name, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol +compiler.misc.incompatible.unrelated.defaults={0} {1} erbt nicht verwandte Standardwerte f\u00FCr {2}({3}) von Typen {4} und {5} + +# 0: kind name, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol +compiler.misc.incompatible.abstract.default={0} {1} erbt abstrakte und Standardmethode f\u00FCr {2}({3}) von Typen {4} und {5} + +# 0: name, 1: kind name, 2: symbol +compiler.err.default.overrides.object.member=Standardmethode {0} in {1} {2} setzt ein Mitglied von java.lang.Object au\u00DFer Kraft + +# 0: type +compiler.err.illegal.static.intf.meth.call=Unzul\u00E4ssiger statischer Schnittstellenmethodenaufruf\nDer Empf\u00E4ngerausdruck muss durch den Typ-Qualifier "{0}" ersetzt werden + +# 0: symbol or type, 1: message segment +compiler.err.illegal.default.super.call=Ung\u00FCltiger Typ-Qualifier {0} in Standardsuperaufruf\n{1} + +# 0: symbol, 1: type +compiler.misc.overridden.default=Methode {0} wird in {1} au\u00DFer Kraft gesetzt + +# 0: symbol, 1: type or symbol +compiler.misc.redundant.supertype=Redundante Schnittstelle {0} wird durch {1} erweitert + +compiler.err.unclosed.char.lit=Nicht geschlossenes Zeichenliteral + +compiler.err.unclosed.comment=Nicht geschlossener Kommentar + +compiler.err.unclosed.str.lit=Nicht geschlossenes Zeichenfolgenliteral + +compiler.err.unclosed.text.block=Nicht geschlossener Textblock + +# 0: string +compiler.err.unsupported.encoding=Nicht unterst\u00FCtzte Codierung: {0} + +compiler.err.io.exception=Fehler beim Lesen der Quelldatei: {0} + +# 0: name +compiler.err.undef.label=Nicht definiertes Label: {0} + +# 0: name +compiler.err.illegal.ref.to.restricted.type=Unzul\u00E4ssige Referenz zu eingeschr\u00E4nktem Typ "{0}" + +# 0: name +compiler.warn.illegal.ref.to.restricted.type=Unzul\u00E4ssige Referenz zu eingeschr\u00E4nktem Typ "{0}" + +# 0: name, 1: source +compiler.err.restricted.type.not.allowed="{0}" ist hier nicht zul\u00E4ssig\nAb Release {1} ist "{0}" ein eingeschr\u00E4nkter Typname, der nicht f\u00FCr Typdeklarationen verwendet werden kann + +# 0: name, 1: source +compiler.warn.restricted.type.not.allowed=Ab Release {1} ist "{0}" ein eingeschr\u00E4nkter Typname, der nicht f\u00FCr Typdeklarationen oder als Elementtyp eines Arrays verwendet werden kann + +# 0: name, 1: source +compiler.warn.restricted.type.not.allowed.preview="{0}" kann in einem zuk\u00FCnftigen Release ein eingeschr\u00E4nkter Typname werden, der nicht f\u00FCr Typdeklarationen oder als Elementtyp eines Arrays verwendet werden kann + +# 0: name (variable), 1: message segment +compiler.err.cant.infer.local.var.type=Typ f\u00FCr lokale Variable {0} kann nicht abgeleitet werden\n({1}) + +# 0: name +compiler.err.restricted.type.not.allowed.here="{0}" ist hier nicht zul\u00E4ssig + +# 0: name +compiler.err.restricted.type.not.allowed.array="{0}" ist nicht als Elementtyp eines Arrays zul\u00E4ssig + +# 0: name +compiler.err.restricted.type.not.allowed.compound="{0}" ist nicht in einer zusammengesetzten Deklaration zul\u00E4ssig + +# 0: fragment +compiler.err.invalid.lambda.parameter.declaration=Ung\u00FCltige Lambda-Parameterdeklaration\n({0}) + +compiler.misc.implicit.and.explicit.not.allowed=Implizit typisierte Parameter k\u00F6nnen nicht mit explizit typisierten Parametern gemischt werden + +compiler.misc.var.and.explicit.not.allowed="var" kann nicht mit explizit typisierten Parametern gemischt werden + +compiler.misc.var.and.implicit.not.allowed="var" kann nicht mit implizit typisierten Parametern gemischt werden + +compiler.misc.local.cant.infer.null=Variablen-Initializer ist "null" + +compiler.misc.local.cant.infer.void=Variablen-Initializer ist "void" + +compiler.misc.local.missing.init="var" kann nicht f\u00FCr Variable ohne Initializer verwendet werden + +compiler.misc.local.lambda.missing.target=Lambda-Ausdruck erfordert einen expliziten Zieltyp + +compiler.misc.local.mref.missing.target=Methodenreferenz erfordert einen expliziten Zieltyp + +compiler.misc.local.array.missing.target=Array-Initializer erfordert einen expliziten Zieltyp + +compiler.misc.local.self.ref="var" kann nicht f\u00FCr selbstreferenzierende Variable verwendet werden + +# 0: message segment, 1: unused +compiler.err.cant.apply.diamond=Typargumente f\u00FCr {0} k\u00F6nnen nicht abgeleitet werden + +# 0: message segment or type, 1: message segment +compiler.err.cant.apply.diamond.1=Typargumente f\u00FCr {0} k\u00F6nnen nicht abgeleitet werden\nGrund: {1} + +# 0: message segment or type, 1: message segment +compiler.misc.cant.apply.diamond.1=Typargumente f\u00FCr {0} k\u00F6nnen nicht abgeleitet werden\nGrund: {1} + +compiler.err.unreachable.stmt=Nicht erreichbare Anweisung + +compiler.err.not.exhaustive=Der Switch-Ausdruck deckt nicht alle m\u00F6glichen Eingabewerte ab + +compiler.err.not.exhaustive.statement=Die Switch-Anweisung deckt nicht alle m\u00F6glichen Eingabewerte ab + +compiler.err.initializer.must.be.able.to.complete.normally=Initializer muss normal abgeschlossen werden k\u00F6nnen + +compiler.err.initializer.not.allowed=Initializer in Schnittstellen nicht zul\u00E4ssig + +# 0: type +compiler.err.unreported.exception.need.to.catch.or.throw=Nicht gemeldete Ausnahme {0}. Muss abgefangen oder deklariert werden, um ausgel\u00F6st zu werden + +# 0: type +compiler.err.unreported.exception.default.constructor=Nicht gemeldete Ausnahme {0} in Standardkonstruktor + +# 0: type, 1: name +compiler.err.unreported.exception.implicit.close=Nicht gemeldete Ausnahme {0}. Muss abgefangen oder deklariert werden, um ausgel\u00F6st zu werden\nAusnahme bei implizitem Aufruf von close() f\u00FCr Ressourcenvariable "{1}" ausgel\u00F6st + +compiler.err.void.not.allowed.here="void"-Typ hier nicht zul\u00E4ssig + +# 0: string +compiler.err.wrong.number.type.args=Falsche Anzahl Typargumente. {0} erforderlich + +# 0: symbol +compiler.err.var.might.already.be.assigned=Variable {0} wurde m\u00F6glicherweise bereits zugewiesen + +# 0: symbol +compiler.err.var.might.not.have.been.initialized=Variable {0} wurde m\u00F6glicherweise nicht initialisiert + +# 0: symbol +compiler.err.var.not.initialized.in.default.constructor=Variable {0} nicht im Standardkonstruktor initialisiert + +# 0: symbol +compiler.err.var.might.be.assigned.in.loop=Variable {0} wurde m\u00F6glicherweise in Schleife zugewiesen + +# 0: symbol, 1: message segment +compiler.err.varargs.invalid.trustme.anno=Ung\u00FCltige {0}-Annotation. {1} + +# 0: type +compiler.misc.varargs.trustme.on.reifiable.varargs=Varargs-Elementtyp {0} ist reifizierbar. + +# 0: type, 1: type +compiler.err.instanceof.reifiable.not.safe={0} kann nicht sicher in {1} konvertiert werden + +# 0: type, 1: type +compiler.err.instanceof.pattern.no.subtype=Ausdruckstyp {0} ist ein Subtyp des Mustertyps {1} + +# 0: symbol +compiler.misc.varargs.trustme.on.non.varargs.meth=Methode {0} ist keine varargs-Methode. + +# 0: symbol +compiler.misc.varargs.trustme.on.non.varargs.accessor=Accessor {0} ist keine varargs-Methode. + +# 0: symbol +compiler.misc.varargs.trustme.on.virtual.varargs=Instanzmethode {0} ist weder final noch privat. + +# 0: symbol +compiler.misc.varargs.trustme.on.virtual.varargs.final.only=Instanzmethode {0} ist nicht final. + +# 0: type, 1: symbol kind, 2: symbol +compiler.misc.inaccessible.varargs.type=Auf den formalen varargs-Elementtyp {0} kann nicht von {1} {2} zugegriffen werden + +# In the following string, {1} will always be the detail message from +# java.io.IOException. +# 0: symbol, 1: string +compiler.err.class.cant.write=Fehler beim Schreiben von {0}: {1} + +# In the following string, {0} is the name of the class in the Java source. +# It really should be used two times.. +# 0: kind name, 1: name +compiler.err.class.public.should.be.in.file={0} {1} ist \u00F6ffentlich und muss in einer Datei namens {1}.java deklariert werden + +## All errors which do not refer to a particular line in the source code are +## preceded by this string. +compiler.err.error=Fehler: + +# The following error messages do not refer to a line in the source code. +compiler.err.cant.read.file=Lesen nicht m\u00F6glich: {0} + +# 0: string +compiler.err.plugin.not.found=Plug-in nicht gefunden: {0} + +# 0: path +compiler.warn.locn.unknown.file.on.module.path=Unbekannte Datei in Modulpfad: {0} + + +# 0: path +compiler.err.locn.bad.module-info=Problem beim Lesen von module-info.class in {0} + +# 0: path +compiler.err.locn.cant.read.directory=Verzeichnis {0} kann nicht gelesen werden + +# 0: path +compiler.err.locn.cant.read.file=Datei {0} kann nicht gelesen werden + +# 0: path +compiler.err.locn.cant.get.module.name.for.jar=Modulname f\u00FCr {0} kann nicht bestimmt werden + +# 0: path +compiler.err.multi-module.outdir.cannot.be.exploded.module=Im Modus f\u00FCr mehrere Module kann das Ausgabeverzeichnis kein entpacktes Modul sein: {0} + +# 0: path +compiler.warn.outdir.is.in.exploded.module=Das Ausgabeverzeichnis befindet sich in einem entpackten Modul: {0} + +# 0: file object +compiler.err.locn.module-info.not.allowed.on.patch.path=module-info.class nicht in Patchpfad zul\u00E4ssig: {0} + +# 0: string +compiler.err.locn.invalid.arg.for.xpatch=Ung\u00FCltiges Argument f\u00FCr --patch-module-Option: {0} + +compiler.err.file.sb.on.source.or.patch.path.for.module=Datei muss sich im Quellpfad oder im Patchpfad f\u00FCr das Modul befinden + +compiler.err.no.java.lang=Package java.lang kann in Plattformklassen nicht gefunden werden + +##### + +# Fatal Errors + +# 0: name +compiler.misc.fatal.err.cant.locate.meth=Schwerwiegender Fehler: Methode {0} kann nicht gefunden werden + +# 0: name +compiler.misc.fatal.err.cant.locate.field=Schwerwiegender Fehler: Feld {0} kann nicht gefunden werden + +# 0: type +compiler.misc.fatal.err.cant.locate.ctor=Schwerwiegender Fehler: Konstruktor f\u00FCr {0} kann nicht gefunden werden + +compiler.misc.fatal.err.cant.close=Schwerwiegender Fehler: Compiler-Ressourcen k\u00F6nnen nicht geschlossen werden + +##### + +## +## miscellaneous strings +## + +compiler.misc.diamond.anonymous.methods.implicitly.override=(aufgrund von <> muss jede nicht private Methode, die in dieser anonymen Klasse deklariert ist, eine Methode aus einem Supertyp au\u00DFer Kraft setzen oder implementieren) + +compiler.misc.source.unavailable=(Quelle nicht verf\u00FCgbar) + +compiler.misc.base.membership=Alle Basisklassen geh\u00F6ren zu dieser Gruppe + +# 0: string, 1: string, 2: boolean +compiler.misc.x.print.processor.info=Prozessor {0} entspricht {1} und gibt {2} zur\u00FCck. + +# 0: number, 1: string, 2: set of symbol, 3: boolean +compiler.misc.x.print.rounds=Runde {0}:\n\tEingabedateien: {1}\n\tAnnotationen: {2}\n\tLetzte Runde: {3} + +# 0: file name +compiler.warn.file.from.future=\u00C4nderungsdatum liegt in der Zukunft f\u00FCr Datei {0} + +##### + +## The following string will appear before all messages keyed as: +## "compiler.note". + +compiler.note.compressed.diags=Einige Meldungen wurden vereinfacht. Wiederholen Sie die Kompilierung mit -Xdiags:verbose, um die vollst\u00E4ndige Ausgabe abzurufen + +# 0: boolean, 1: symbol +compiler.note.lambda.stat=Lambda-Ausdruck wird \u00FCbersetzt\nAlternative Metafactory = {0}\nSynthetische Methode = {1} + +# 0: boolean, 1: unused +compiler.note.mref.stat=Methodenreferenz wird \u00FCbersetzt\nAlternative Metafactory = {0}\n +# 0: boolean, 1: symbol +compiler.note.mref.stat.1=Methodenreferenz wird \u00FCbersetzt\nAlternative Metafactory = {0}\nBridgemethode = {1} + +compiler.note.note=Hinweis: + +# 0: file name +compiler.note.deprecated.filename={0} verwendet oder \u00FCberschreibt eine veraltete API. + +compiler.note.deprecated.plural=Einige Eingabedateien verwenden oder \u00FCberschreiben eine veraltete API. + +# The following string may appear after one of the above deprecation +# messages. +compiler.note.deprecated.recompile=Wiederholen Sie die Kompilierung mit -Xlint:deprecation, um Details zu erhalten. + +# 0: file name +compiler.note.deprecated.filename.additional={0} hat weitere Verwendungen oder Overrides einer veralteten API. + +compiler.note.deprecated.plural.additional=Einige Eingabedateien verwenden oder \u00FCberschreiben zus\u00E4tzlich eine veraltete API. + +# 0: file name +compiler.note.removal.filename={0} verwendet oder \u00FCberschreibt eine veraltete API, die zum Entfernen markiert ist. + +compiler.note.removal.plural=Einige Eingabedateien verwenden oder \u00FCberschreiben eine veraltete API, die zum Entfernen markiert ist. + +# The following string may appear after one of the above removal messages. +compiler.note.removal.recompile=Wiederholen Sie die Kompilierung mit -Xlint:removal, um Details zu erhalten. + +# 0: file name +compiler.note.removal.filename.additional={0} hat weitere Verwendungen oder Overrides einer veralteten API, die zum Entfernen markiert ist. + +compiler.note.removal.plural.additional=Einige Eingabedateien verwenden oder \u00FCberschreiben zus\u00E4tzlich eine veraltete API, die zum Entfernen markiert ist. + +# 0: file name +compiler.note.unchecked.filename={0} verwendet nicht gepr\u00FCfte oder unsichere Vorg\u00E4nge. + +compiler.note.unchecked.plural=Einige Eingabedateien verwenden nicht gepr\u00FCfte oder unsichere Vorg\u00E4nge. + +# The following string may appear after one of the above unchecked messages. +compiler.note.unchecked.recompile=Wiederholen Sie die Kompilierung mit -Xlint:unchecked, um Details zu erhalten. + +# 0: file name +compiler.note.unchecked.filename.additional={0} weist weitere nicht gepr\u00FCfte oder unsichere Vorg\u00E4nge auf. + +compiler.note.unchecked.plural.additional=Einige Eingabedateien verwenden zus\u00E4tzlich nicht gepr\u00FCfte oder unsichere Vorg\u00E4nge. + +# 0: file name, 1: source +compiler.note.preview.filename={0} verwendet Vorschaufeatures von Java SE {1}. + +# 0: source +compiler.note.preview.plural=Einige Eingabedateien verwenden Vorschaufeatures von Java SE {0}. + +# The following string may appear after one of the above deprecation +# messages. +compiler.note.preview.recompile=Wiederholen Sie die Kompilierung mit -Xlint:preview, um Details zu erhalten. + +# 0: file name, 1: source +compiler.note.preview.filename.additional={0} hat weitere Verwendungen von Vorschaufeatures von Java SE {1}. + +# 0: source +compiler.note.preview.plural.additional=Einige Eingabedateien verwenden zus\u00E4tzlich Vorschaufeatures von Java SE {0}. + +# Notes related to annotation processing + +# Print a client-generated note; assumed to be localized, no translation required +# 0: string +compiler.note.proc.messager={0} + +# 0: string, 1: string, 2: string +compiler.note.multiple.elements=Mehrere Elemente namens "{1}" in Modulen "{2}" wurden von javax.lang.model.util.Elements.{0} gefunden. + +##### + +# 0: number +compiler.misc.count.error={0} Fehler + +# 0: number +compiler.misc.count.error.plural={0} Fehler + +# 0: number, 1: number +compiler.misc.count.error.recompile=Nur die ersten {0} Fehler von insgesamt {1} werden angezeigt. Mit -Xmaxerrs k\u00F6nnen Sie mehr Fehler anzeigen + +# 0: number, 1: number +compiler.misc.count.warn.recompile=Nur die ersten {0} Warnungen von insgesamt {1} werden angezeigt. Mit -Xmaxwarns k\u00F6nnen Sie mehr Warnungen anzeigen + +# 0: number +compiler.misc.count.warn={0} Warnung + +# 0: number +compiler.misc.count.warn.plural={0} Warnungen + +compiler.misc.version.not.available=(Versionsinformationen nicht verf\u00FCgbar) + +## extra output when using -verbose (JavaCompiler) + +# 0: symbol +compiler.misc.verbose.checking.attribution=[{0} wird gepr\u00FCft] + +# 0: string +compiler.misc.verbose.parsing.done=[Parsen abgeschlossen: {0} ms] + +# 0: file name +compiler.misc.verbose.parsing.started=[Parsen gestartet: {0}] + +# 0: string +compiler.misc.verbose.total=[{0} ms gesamt] + +# 0: file name +compiler.misc.verbose.wrote.file=[{0} geschrieben] + +## extra output when using -verbose (code/ClassReader) +# 0: string +compiler.misc.verbose.loading=[{0} wird geladen] + +# 0: string +compiler.misc.verbose.sourcepath=[Suchpfad f\u00FCr Quelldateien: {0}] + +# 0: string +compiler.misc.verbose.classpath=[Suchpfad f\u00FCr Klassendateien: {0}] + +## extra output when using -prompt (util/Log) +compiler.misc.resume.abort=F)ortsetzen, A)bbruch> + +##### + +## +## warnings +## + +## All warning messages are preceded by the following string. +compiler.warn.warning=Warnung: + +## Warning messages may also include the following prefix to identify a +## lint option +# 0: option name +compiler.warn.lintOption=[{0}] + +# 0: symbol +compiler.warn.constant.SVUID=serialVersionUID muss Konstante in Klasse {0} sein + +# 0: path +compiler.warn.dir.path.element.not.found=Ung\u00FCltiges Pfadelement "{0}": Verzeichnis nicht vorhanden + +# 0: file name +compiler.warn.dir.path.element.not.directory=Ung\u00FCltiges Pfadelement "{0}": kein Verzeichnis + +# 0: symbol, 1: symbol, 2: symbol +compiler.warn.missing-explicit-ctor=Klasse {0} in exportiertem Package {1} deklariert keine expliziten Konstruktoren und stellt daher einen Standardkonstruktor f\u00FCr Clients des Moduls {2} bereit + +compiler.warn.strictfp=Ab Release 17 werden alle Gleitkommaausdr\u00FCcke streng ausgewertet. Daher ist "strictfp" nicht erforderlich + +compiler.warn.finally.cannot.complete=Finally-Klausel kann nicht normal abgeschlossen werden + +# 0: name +compiler.warn.poor.choice.for.module.name=Modulnamenskomponente {0} darf keine Ziffern am Ende enthalten + +# 0: string +compiler.warn.incubating.modules=Inkubatormodul(e) verwendet: {0} + +# 0: symbol, 1: symbol +compiler.warn.has.been.deprecated={0} in {1} ist veraltet + +# 0: symbol, 1: symbol +compiler.warn.has.been.deprecated.for.removal={0} in {1} ist veraltet und wurde zum Entfernen markiert + +# 0: symbol +compiler.warn.is.preview={0} ist eine Vorschau-API, die in einem zuk\u00FCnftigen Release entfernt werden kann. + +# 0: symbol +compiler.err.is.preview={0} ist eine Vorschau-API, die standardm\u00E4\u00DFig deaktiviert ist.\n(Verwenden Sie --enable-preview, um Vorschau-APIs zu aktivieren) + +# 0: symbol +compiler.warn.is.preview.reflective={0} ist eine reflektive Vorschau-API, die in einem zuk\u00FCnftigen Release entfernt werden kann. + +# 0: symbol +compiler.warn.has.been.deprecated.module=Modul {0} ist veraltet + +# 0: symbol +compiler.warn.has.been.deprecated.for.removal.module=Modul {0} ist veraltet und wurde zum Entfernen markiert + +# 0: symbol +compiler.warn.sun.proprietary={0} ist eine interne propriet\u00E4re API, die in einem zuk\u00FCnftigen Release entfernt werden kann + +compiler.warn.illegal.char.for.encoding=Nicht zuordenbares Zeichen f\u00FCr Codierung {0} + +# 0: symbol +compiler.warn.improper.SVUID=serialVersionUID muss als "static final" in Klasse {0} deklariert sein + +compiler.warn.improper.SPF=serialPersistentFields muss als "private static final" deklariert sein, um in Kraft zu treten + +compiler.warn.SPF.null.init=serialPersistentFields tritt bei Initialisierung als Null nicht in Kraft.\nF\u00FChren Sie die Initialisierung zu einem leeren Array aus, um keine Felder anzugeben + + +# 0: type, 1: type +compiler.warn.inexact.non-varargs.call=Nicht-varargs-Aufruf von varargs-Methode mit ungenauem Argumenttyp f\u00FCr den letzten Parameter.\nF\u00FChren Sie f\u00FCr einen varargs-Aufruf eine Umwandlung mit Cast in {0} aus\nF\u00FChren Sie f\u00FCr einen Nicht-varargs-Aufruf eine Umwandlung mit Cast in {1} aus, um diese Warnung zu unterdr\u00FCcken + +# 0: list of type +compiler.warn.unreachable.catch=Nicht erreichbare Catch-Klausel\nAusgel\u00F6ster Typ {0} wurde bereits abgefangen + +# 0: list of type +compiler.warn.unreachable.catch.1=Nicht erreichbare Catch-Klausel\nAusgel\u00F6ste Typen {0} wurden bereits abgefangen + +# 0: symbol +compiler.warn.long.SVUID=serialVersionUID muss den Typ "long" in Klasse {0} aufweisen + +compiler.warn.OSF.array.SPF=serialPersistentFields muss den Typ "java.io.ObjectStreamField[]" aufweisen, um in Kraft zu treten + +# 0: symbol +compiler.warn.missing.SVUID=Serialisierbare Klasse {0} enth\u00E4lt keine Definition von serialVersionUID + +# 0: name +compiler.warn.serializable.missing.access.no.arg.ctor=Zugriff auf einen no-arg-Konstruktor in der ersten nicht serialisierbaren Superklasse {0} nicht m\u00F6glich + +# 0: name +compiler.warn.serial.method.not.private=Serialisierungsbezogene Methode {0} nicht als privat deklariert + +# 0: name +compiler.warn.serial.concrete.instance.method=Serialisierungsbezogene Methode {0} muss eine konkrete Instanzmethode sein, um in Kraft zu treten. Sie darf nicht abstrakt oder statisch sein + +# 0: name +compiler.warn.serial.method.static=Serialisierungsbezogene Methode {0} ist als statisch deklariert. Sie muss stattdessen eine Instanzmethode sein, um in Kraft zu treten. + +# 0: name +compiler.warn.serial.method.no.args=Serialisierungsbezogene Methode {0} darf keine Parameter aufweisen, um in Kraft zu treten + +# 0: name, 1: number +compiler.warn.serial.method.one.arg=Serialisierungsbezogene Methode {0} muss genau einen Parameter aufweisen, um in Kraft zu treten. Sie darf nicht {1} Parameter enthalten + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.parameter.type=Der einzige Parameter der serialisierungsbezogenen Methode {0} muss den Typ {1} haben, um in Kraft zu treten. Er darf nicht den Typ {2} aufweisen + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.unexpected.return.type=Serialisierungsbezogene Methode {0} wurde mit dem R\u00FCckgabetyp {1} und nicht dem erwarteten Typ {2} deklariert.\nMit dieser Deklaration ist die Methode ung\u00FCltig f\u00FCr die Serialisierung + +# 0: name, 1: type +compiler.warn.serial.method.unexpected.exception=Serialisierungsbezogene Methode {0} wurde zum Ausl\u00F6sen eines unerwarteten Typs {1} deklariert + +compiler.warn.ineffectual.serial.field.interface=serialPersistentFields ist in einer Schnittstelle nicht effektiv + +# 0: string +compiler.warn.ineffectual.serial.field.enum=Serialisierungsbezogenes Feld {0} ist in einer Enum-Klasse nicht effektiv + +# 0: string +compiler.warn.ineffectual.serial.method.enum=Serialisierungsbezogene Methode {0} ist in einer Enum-Klasse nicht effektiv + +compiler.warn.ineffectual.serial.field.record=serialPersistentFields ist in einer Datensatzklasse nicht effektiv + +# 0: string +compiler.warn.ineffectual.serial.method.record=Serialisierungsbezogene Methode {0} ist in einer Datensatzklasse nicht effektiv + +# 0: name +compiler.warn.ineffectual.serial.method.externalizable=Serialisierungsbezogene Methode {0} ist in einer externalisierbaren Klasse nicht effektiv + +compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields ist in einer externalisierbaren Klasse nicht effektiv + +compiler.warn.externalizable.missing.public.no.arg.ctor=Eine externalisierbare Klasse erfordert einen \u00F6ffentlichen no-arg-Konstruktor + +compiler.warn.non.serializable.instance.field=Nicht transientes Instanzfeld einer serialisierbaren Klasse mit einem nicht serialisierbaren Typ deklariert + +# 0: type +compiler.warn.non.serializable.instance.field.array=Nicht transientes Instanzfeld einer serialisierbaren Klasse wurde mit einem Array mit einem nicht serialisierbaren Basiskomponententyp {0} deklariert + +compiler.warn.non.private.method.weaker.access=Serialisierungsbezogene Methode, die in einer Schnittstelle als nicht privat deklariert ist, verhindert,\ndass Klassen, die die Schnittstelle implementieren, die Methode als privat deklarieren + +compiler.warn.default.ineffective=Serialisierungsbezogene Standardmethode aus einer Schnittstelle wird nicht von der Serialisierung f\u00FCr eine implementierende Klasse ausgef\u00FChrt + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.warn.potentially.ambiguous.overload={0} in {1} ist m\u00F6glicherweise mehrdeutig mit {2} in {3} + +# 0: message segment +compiler.warn.override.varargs.missing={0}. Au\u00DFer Kraft gesetzte Methode umfasst kein "..." + +# 0: message segment +compiler.warn.override.varargs.extra={0}. In au\u00DFer Kraft setzender Methode fehlt "..." + +# 0: message segment +compiler.warn.override.bridge={0}. Au\u00DFer Kraft setzende Methode ist eine Bridgemethode + +# 0: symbol +compiler.warn.pkg-info.already.seen=Die Datei package-info.java wurde bereits f\u00FCr Package {0} gefunden + +# 0: path +compiler.warn.path.element.not.found=Ung\u00FCltiges Pfadelement "{0}": Datei oder Verzeichnis nicht vorhanden + +compiler.warn.possible.fall-through.into.case=M\u00F6glicher Fallthrough in Case + +# 0: type +compiler.warn.redundant.cast=Redundantes Casting in {0} + +# 0: number +compiler.warn.position.overflow=Positionscodierungs\u00FCberlauf bei Zeile {0} + +# 0: file name, 1: number, 2: number +compiler.warn.big.major.version={0}: Hauptversion {1} ist neuer als {2}, die h\u00F6chste Hauptversion, die von diesem Compiler unterst\u00FCtzt wird.\nEs wird empfohlen, dass Sie den Compiler upgraden. + +# 0: kind name, 1: symbol +compiler.warn.static.not.qualified.by.type=Statische {0} muss mit Typname {1} anstelle eines Ausdrucks qualifiziert werden + +# 0: string +compiler.warn.source.no.bootclasspath=Bootstrap Classpath nicht zusammen mit -source {0} festgelegt + +# 0: string +compiler.warn.source.no.system.modules.path=Systemmodulpfad nicht zusammen mit -source {0} festgelegt + +# 0: string +compiler.warn.option.obsolete.source=Quellwert {0} ist veraltet und wird in einem zuk\u00FCnftigen Release entfernt + +# 0: target +compiler.warn.option.obsolete.target=Zielwert {0} ist veraltet und wird in einem zuk\u00FCnftigen Release entfernt + +# 0: string, 1: string +compiler.err.option.removed.source=Quelloption {0} wird nicht mehr unterst\u00FCtzt. Verwenden Sie {1} oder h\u00F6her. + +# 0: target, 1: target +compiler.err.option.removed.target=Zieloption {0} wird nicht mehr unterst\u00FCtzt. Verwenden Sie {1} oder h\u00F6her. + + +# 0: target, 1: target +compiler.warn.option.parameters.unsupported=-parameters wird f\u00FCr Zielwert {0} nicht unterst\u00FCtzt. Verwenden Sie {1} oder h\u00F6her. + +compiler.warn.option.obsolete.suppression=Verwenden Sie -Xlint:-options, um Warnungen zu veralteten Optionen zu unterdr\u00FCcken. + +# 0: name, 1: number, 2: number, 3: number, 4: number +compiler.warn.future.attr={0}-Attribut, das in Klassendateien der Version {1}.{2} eingef\u00FChrt wurde, wird in Klassendateien der Version {3}.{4} ignoriert + +compiler.warn.requires.automatic=Erfordert Direktive f\u00FCr ein automatisches Modul + +compiler.warn.requires.transitive.automatic=Erfordert transitive-Direktive f\u00FCr ein automatisches Modul + +# Warnings related to annotation processing +# 0: string +compiler.warn.proc.package.does.not.exist=Package {0} ist nicht vorhanden + +# 0: string +compiler.warn.proc.file.reopening=Versuch, mehrmals eine Datei f\u00FCr "{0}" zu erstellen + +# 0: string +compiler.warn.proc.type.already.exists=Es ist bereits eine Datei f\u00FCr Typ "{0}" im Quellpfad oder Classpath vorhanden + +# 0: string +compiler.warn.proc.type.recreate=Versuch, mehrmals eine Datei f\u00FCr Typ "{0}" zu erstellen + +# 0: string +compiler.warn.proc.illegal.file.name=Datei kann nicht f\u00FCr unzul\u00E4ssigen Namen "{0}" erstellt werden. + +# 0: string, 1: string +compiler.warn.proc.suspicious.class.name=Datei f\u00FCr einen Typ, dessen Name mit {1} endet, wird erstellt: "{0}" + +# 0: string +compiler.warn.proc.file.create.last.round=Datei f\u00FCr Typ "{0}", die in der letzten Runde erstellt wurde, wird keiner Annotationsverarbeitung unterzogen. + +# 0: string, 1: string +compiler.warn.proc.malformed.supported.string=Nicht wohlgeformte Zeichenfolge "{0}" f\u00FCr eine unterst\u00FCtzte Annotationsschnittstelle von Prozessor "{1}" zur\u00FCckgegeben + +# 0: set of string +compiler.warn.proc.annotations.without.processors=Diese Annotationen wurden von keinem Prozessor beansprucht: {0} + +# 0: source version, 1: string, 2: string +compiler.warn.proc.processor.incompatible.source.version=Unterst\u00FCtzte Quellversion "{0}" von Annotationsprozessor "{1}" kleiner als -source "{2}" + +# 0: string, 1: string +compiler.warn.proc.duplicate.option.name=Doppelte unterst\u00FCtzte Option "{0}" von Annotationsprozessor "{1}" zur\u00FCckgegeben + +# 0: string, 1: string +compiler.warn.proc.duplicate.supported.annotation=Doppelte unterst\u00FCtzte Annotationsschnittstelle "{0}" von Annotationsprozessor "{1}" zur\u00FCckgegeben + +# 0: string +compiler.warn.proc.redundant.types.with.wildcard=Annotationsprozessor "{0}" unterst\u00FCtzt redundant sowohl "*" als auch andere Annotationsschnittstellen + +compiler.warn.proc.proc-only.requested.no.procs=Annotationsverarbeitung ohne Kompilierung angefordert, aber keine Prozessoren gefunden. + +compiler.warn.proc.use.implicit=Implizit kompilierte Dateien wurden keiner Annotationsverarbeitung unterzogen.\nVerwenden Sie -implicit, um eine Policy f\u00FCr die implizite Kompilierung anzugeben. + +compiler.warn.proc.use.proc.or.implicit=Implizit kompilierte Dateien wurden keiner Annotationsverarbeitung unterzogen.\nVerwenden Sie -proc:none, um die Annotationsverarbeitung zu deaktivieren, oder -implicit, um eine Policy f\u00FCr die implizite Kompilierung anzugeben. + +# Print a client-generated warning; assumed to be localized, no translation required +# 0: string +compiler.warn.proc.messager={0} + +# 0: set of string +compiler.warn.proc.unclosed.type.files=Nicht geschlossene Dateien f\u00FCr die Typen "{0}". Diese Typen werden keiner Annotationsverarbeitung unterzogen + +# 0: string +compiler.warn.proc.unmatched.processor.options=Die folgenden Optionen wurden von keinem Prozessor erkannt: "{0}" + +compiler.warn.try.explicit.close.call=Expliziter Aufruf von close() f\u00FCr eine automatisch schlie\u00DFbare Ressource + +# 0: symbol +compiler.warn.try.resource.not.referenced=Automatisch schlie\u00DFbare Ressource {0} wird nie im Body der entsprechenden try-Anweisung referenziert + +# 0: type +compiler.warn.try.resource.throws.interrupted.exc=Automatisch schlie\u00DFbare Ressource {0} umfasst die Mitgliedsmethode close(), die InterruptedException ausl\u00F6sen k\u00F6nnte + +compiler.warn.unchecked.assign=Nicht gepr\u00FCfte Zuweisung: {0} zu {1} + +# 0: symbol, 1: type +compiler.warn.unchecked.assign.to.var=Nicht gepr\u00FCfte Zuweisung zu Variable {0} als Mitglied des Raw-Typs {1} + +# 0: symbol, 1: type +compiler.warn.unchecked.call.mbr.of.raw.type=Nicht gepr\u00FCfter Aufruf von {0} als Mitglied des Raw-Typs {1} + +compiler.warn.unchecked.cast.to.type=Nicht gepr\u00FCftes Casting zu Typ {0} + +# 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +compiler.warn.unchecked.meth.invocation.applied=Nicht gepr\u00FCfter Methodenaufruf: {0} {1} in {4} {5} wird auf die angegebenen Typen angewendet\nErforderlich: {2}\nErmittelt: {3} + +# 0: type +compiler.warn.unchecked.generic.array.creation=Nicht gepr\u00FCfte Erstellung eines generischen Arrays f\u00FCr varargs-Parameter des Typs {0} + +# 0: type +compiler.warn.unchecked.varargs.non.reifiable.type=M\u00F6glich Heap-Besch\u00E4digung aus parametrisiertem vararg-Typ {0} + +# 0: symbol +compiler.warn.varargs.unsafe.use.varargs.param=Varargs-Methode k\u00F6nnte Heap-Besch\u00E4digung aus nicht reifizierbarem varargs-Parameter {0} verursachen + +compiler.warn.missing.deprecated.annotation=Veraltetes Element ist nicht mit @Deprecated-Annotation versehen + +# 0: kind name +compiler.warn.deprecated.annotation.has.no.effect=@Deprecated-Annotation hat keine Auswirkung auf diese {0}-Deklaration + +# 0: string +compiler.warn.invalid.path=Ung\u00FCltiger Dateiname: {0} + +compiler.warn.doclint.not.available=Kein Serviceprovider f\u00FCr doclint verf\u00FCgbar + +# 0: string +compiler.err.invalid.path=Ung\u00FCltiger Dateiname: {0} + + +# 0: path +compiler.warn.invalid.archive.file=Unerwartete Datei in Pfad: {0} + +# 0: path +compiler.warn.unexpected.archive.file=Unerwartete Erweiterung f\u00FCr Archivdatei: {0} + +# 0: path +compiler.err.no.zipfs.for.archive=Kein Dateisystemprovider zur Verarbeitung dieser Datei verf\u00FCgbar: {0} + +compiler.warn.div.zero=Division durch Null + +compiler.warn.empty.if=Leere Anweisung nach "if" + +# 0: type, 1: name +compiler.warn.annotation.method.not.found=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden + +# 0: type, 1: name, 2: message segment +compiler.warn.annotation.method.not.found.reason=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden: {2} + +# 0: file object, 1: symbol, 2: name +compiler.warn.unknown.enum.constant=Unbekannte Enum-Konstante {1}.{2} + +# 0: file object, 1: symbol, 2: name, 3: message segment +compiler.warn.unknown.enum.constant.reason=Unbekannte Enum-Konstante {1}.{2}\nGrund: {3} + +# 0: type, 1: type +compiler.warn.raw.class.use=Raw-Typ gefunden: {0}\nTypargumente f\u00FCr generische Klasse {1} fehlen + +compiler.warn.diamond.redundant.args=Redundante Typargumente in neuem Ausdruck (verwenden Sie stattdessen den Rautenoperator). + +compiler.warn.local.redundant.type=Redundanter Typ f\u00FCr lokale Variable (ersetzen Sie den expliziten Typ durch "var"). + +compiler.warn.potential.lambda.found=Die Erstellung dieser anonymen inneren Klasse kann in einen Lambda-Ausdruck umgewandelt werden. + +compiler.warn.method.redundant.typeargs=Redundante Typargumente in Methodenaufruf. + +# 0: symbol, 1: message segment +compiler.warn.varargs.redundant.trustme.anno=Redundante {0}-Annotation. {1} + +# 0: symbol +compiler.warn.access.to.member.from.serializable.element=Zugriff auf Mitglied {0} aus serialisierbarem Element kann \u00F6ffentlich f\u00FCr nicht vertrauensw\u00FCrdigen Code zug\u00E4nglich sein + +# 0: symbol +compiler.warn.access.to.member.from.serializable.lambda=Zugriff auf Mitglied {0} aus serialisierbarem Lambda kann \u00F6ffentlich f\u00FCr nicht vertrauensw\u00FCrdigen Code zug\u00E4nglich sein + +##### + +## The following are tokens which are non-terminals in the language. They should +## be named as JLS3 calls them when translated to the appropriate language. +compiler.misc.token.identifier= + +compiler.misc.token.character= + +compiler.misc.token.string= + +compiler.misc.token.integer= + +compiler.misc.token.long-integer= + +compiler.misc.token.float= + +compiler.misc.token.double= + +compiler.misc.token.bad-symbol= + +compiler.misc.token.end-of-input= + +## The argument to the following string will always be one of the following: +## 1. one of the above non-terminals +## 2. a keyword (JLS1.8) +## 3. a boolean literal (JLS3.10.3) +## 4. the null literal (JLS3.10.7) +## 5. a Java separator (JLS3.11) +## 6. an operator (JLS3.12) +## +## This is the only place these tokens will be used. +# 0: token +compiler.err.expected={0} erwartet + +# 0: string +compiler.err.expected.str={0} erwartet + +# 0: token, 1: token +compiler.err.expected2={0} oder {1} erwartet + +# 0: token, 1: token, 2: token +compiler.err.expected3={0}, {1} oder {2} erwartet + +# 0: token, 1: token, 2: token, 3: string +compiler.err.expected4={0}, {1}, {2} oder {3} erwartet + +compiler.err.premature.eof=Dateiende beim Parsen erreicht + +compiler.err.enum.constant.expected=Hier wird eine Enum-Konstante erwartet + +compiler.err.enum.constant.not.expected=Hier wird keine Enum-Konstante erwartet + +## The following are related in form, but do not easily fit the above paradigm. +compiler.err.expected.module.or.open="module" oder "open" erwartet + +compiler.err.dot.class.expected=".class" erwartet + +## The argument to this string will always be either 'case' or 'default'. +# 0: token +compiler.err.orphaned={0} verwaist + +# 0: name +compiler.misc.anonymous.class= + +# 0: name, 1: type +compiler.misc.type.captureof=capture#{0} von {1} + +compiler.misc.type.captureof.1=capture#{0} + +compiler.misc.type.none= + +compiler.misc.unnamed.package=Unbenanntes Package + +compiler.misc.unnamed.module=Unbenanntes Modul + +##### + +# 0: symbol, 1: message segment +compiler.err.cant.access=Kein Zugriff auf {0}\n{1} + +# 0: name +compiler.misc.bad.class.file=Klassendatei ist ung\u00FCltig f\u00FCr Klasse {0} + +# 0: file name, 1: string (expected constant pool entry type), 2: number (constant pool index) +compiler.misc.bad.const.pool.entry=Ung\u00FCltiger Konstantenpooleintrag in {0}\n{1} bei Index {2} erwartet + +# 0: file name, 1: number (constant pool index), 2: number (constant pool size) +compiler.misc.bad.const.pool.index=Ung\u00FCltiger Konstantenpoolindex in {0}\nIndex {1} liegt nicht innerhalb der Poolgr\u00F6\u00DFe {2}. + +# 0: file name, 1: message segment +compiler.misc.bad.class.file.header=Ung\u00FCltige Klassendatei: {0}\n{1}\nEntfernen Sie die Datei, oder stellen Sie sicher, dass sie im richtigen Unterverzeichnis des Classpath vorhanden ist. + +# 0: file name, 1: message segment +compiler.misc.bad.source.file.header=Ung\u00FCltige Quelldatei: {0}\n{1}\nEntfernen Sie die Datei, oder stellen Sie sicher, dass sie im richtigen Unterverzeichnis des Quellpfades vorhanden ist. + +## The following are all possible strings for the second argument ({1}) of the +## above strings. +compiler.misc.bad.class.signature=Ung\u00FCltige Klassensignatur: {0} + +#0: symbol, 1: symbol +compiler.misc.bad.enclosing.class=Ung\u00FCltige einschlie\u00DFende Klasse f\u00FCr {0}: {1} + +# 0: symbol +compiler.misc.bad.enclosing.method=Ung\u00FCltiges einschlie\u00DFendes Methodenattribut f\u00FCr Klasse {0} + +compiler.misc.bad.runtime.invisible.param.annotations=Ung\u00FCltiges RuntimeInvisibleParameterAnnotations-Attribut: {0} + +compiler.misc.bad.const.pool.tag=Ung\u00FCltiges Konstantenpooltag: {0} + +compiler.misc.bad.const.pool.tag.at=Ung\u00FCltiges Konstantenpooltag {0} bei {1} + +compiler.misc.unexpected.const.pool.tag.at=Unerwartetes Konstantenpooltag {0} bei {1} + +compiler.misc.bad.signature=Ung\u00FCltige Signatur: {0} + +compiler.misc.bad.type.annotation.value=Ung\u00FCltiger Typ f\u00FCr Annotationszielwert: {0} + +compiler.misc.bad.module-info.name=Ung\u00FCltiger Klassenname + +compiler.misc.class.file.wrong.class=Klassendatei enth\u00E4lt falsche Klasse: {0} + +compiler.misc.module.info.invalid.super.class=module-info mit ung\u00FCltiger Superklasse + +# 0: name +compiler.misc.class.file.not.found=Klassendatei f\u00FCr {0} nicht gefunden + +# 0: string (constant value), 1: symbol (constant field), 2: type (field type) +compiler.misc.bad.constant.range=Konstantenwert "{0}" f\u00FCr {1} liegt au\u00DFerhalb des erwarteten Bereichs f\u00FCr {2} + +# 0: string (constant value), 1: symbol (constant field), 2: string (expected class) +compiler.misc.bad.constant.value=Ung\u00FCltiger Konstantenwert "{0}" f\u00FCr {1}. {2} erwartet + +# 0: type (field type) +compiler.misc.bad.constant.value.type=Variable des Typs "{0}" darf keinen Konstantenwert aufweisen, aber es wurde einer f\u00FCr sie angegeben + +# 0: string (classfile major version), 1: string (classfile minor version) +compiler.misc.invalid.default.interface=Standardmethode in Klassendatei der Version {0}.{1} gefunden + +# 0: string (classfile major version), 1: string (classfile minor version) +compiler.misc.invalid.static.interface=Statische Methode in Klassendatei der Version {0}.{1} gefunden + +# 0: string (classfile major version), 1: string (classfile minor version) +compiler.misc.anachronistic.module.info=Moduldeklaration in Klassendatei der Version {0}.{1} gefunden + +compiler.misc.module.info.definition.expected=module-info-Definition erwartet + +# 0: name +compiler.misc.file.doesnt.contain.class=Datei enth\u00E4lt nicht Klasse {0} + +# 0: symbol +compiler.misc.file.does.not.contain.package=Datei enth\u00E4lt nicht Package {0} + +compiler.misc.file.does.not.contain.module=Datei enth\u00E4lt keine Moduldeklaration + +compiler.misc.illegal.start.of.class.file=Unzul\u00E4ssiger Klassendateibeginn + +# 0: name +compiler.misc.method.descriptor.invalid=Methodendeskriptor ung\u00FCltig f\u00FCr {0} + +compiler.misc.unable.to.access.file=Zugriff auf Datei nicht m\u00F6glich: {0} + +compiler.misc.unicode.str.not.supported=Unicode-Zeichenfolge wird in Klassendatei nicht unterst\u00FCtzt + +compiler.misc.undecl.type.var=Nicht deklarierte Typvariable: {0} + +compiler.misc.malformed.vararg.method=Klassendatei enth\u00E4lt nicht wohlgeformte Methode mit variabler Argumentanzahl: {0} + +compiler.misc.wrong.version=Klassendatei hat die falsche Version {0}.{1}. Sie muss {2}.{3} lauten + +##### + +# 0: type, 1: type or symbol +compiler.err.not.within.bounds=Typargument {0} liegt nicht innerhalb des g\u00FCltigen Bereichs von Typvariable {1} + +## The following are all possible strings for the second argument ({1}) of the +## above string. + +## none yet... + +##### + +# 0: message segment +compiler.err.prob.found.req=Inkompatible Typen: {0} + +# 0: message segment +compiler.misc.prob.found.req=Inkompatible Typen: {0} + +# 0: message segment, 1: type, 2: type +compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} + +# 0: type, 1: type +compiler.misc.inconvertible.types={0} kann nicht in {1} konvertiert werden + +# 0: type, 1: type +compiler.misc.possible.loss.of.precision=M\u00F6glicher Verlust bei Konvertierung von {0} in {1} + +compiler.misc.unchecked.assign=Nicht gepr\u00FCfte Konvertierung + +# compiler.misc.storecheck=\ +# assignment might cause later store checks to fail +# compiler.misc.unchecked=\ +# assigned array cannot dynamically check its stores +compiler.misc.unchecked.cast.to.type=Nicht gepr\u00FCftes Casting + +# compiler.err.star.expected=\ +# ''*'' expected +# compiler.err.no.elem.type=\ +# \[\*\] cannot have a type + +# 0: message segment +compiler.misc.try.not.applicable.to.type=try-with-resources nicht auf Variablentyp anwendbar\n({0}) + +##### + +# 0: object, 1: message segment +compiler.err.type.found.req=Unerwarteter Typ\nErforderlich: {1}\nErmittelt: {0} + +## The following are all possible strings for the first argument ({0}) of the +## above string. +compiler.misc.type.req.class=Klasse + +compiler.misc.type.req.class.array=Klasse oder Array + +compiler.misc.type.req.array.or.iterable=Array oder java.lang.Iterable + +compiler.misc.type.req.ref=Referenz + +compiler.misc.type.req.exact=Klasse oder Schnittstelle ohne Grenzwerte + +# 0: type +compiler.misc.type.parameter=Typparameter {0} + +##### + +## The following are all possible strings for the last argument of all those +## diagnostics whose key ends in ".1" + +# 0: type, 1: list of type +compiler.misc.no.unique.maximal.instance.exists=Keine eindeutige maximale Instanz f\u00FCr Typvariable {0} mit oberen Grenzwerten {1} vorhanden + +# 0: type, 1: list of type +compiler.misc.no.unique.minimal.instance.exists=Keine eindeutige minimale Instanz f\u00FCr Typvariable {0} mit unteren Grenzwerten {1} vorhanden + +# 0: type, 1: list of type +compiler.misc.incompatible.upper.bounds=Inferenzvariable {0} hat inkompatible obere Grenzwerte {1} + +# 0: type, 1: list of type +compiler.misc.incompatible.eq.bounds=Inferenzvariable {0} hat inkompatible Gleichheits-Constraints {1} + +# 0: type, 1: fragment, 2: fragment +compiler.misc.incompatible.bounds=Inferenzvariable {0} hat inkompatible Grenzwerte\n{1}\n{2} + +# 0: list of type +compiler.misc.lower.bounds=Untere Grenzwerte: {0} + +# 0: list of type +compiler.misc.eq.bounds=Gleichheits-Constraints: {0} + +# 0: list of type +compiler.misc.upper.bounds=Untere Grenzwerte: {0} + +# 0: list of type, 1: type, 2: type +compiler.misc.infer.no.conforming.instance.exists=Keine Instanzen von Typvariablen {0} vorhanden, sodass {1} {2} entspricht + +# 0: list of type, 1: message segment +compiler.misc.infer.no.conforming.assignment.exists=Typvariable(n) {0} nicht ableitbar\n(nicht \u00FCbereinstimmende Argumente; {1}) + +# 0: list of type +compiler.misc.infer.arg.length.mismatch=Typvariable(n) {0} nicht ableitbar\n(Liste der tats\u00E4chlichen Argumente hat eine andere L\u00E4nge als die der formalen Argumente) + +# 0: list of type, 1: message segment +compiler.misc.infer.varargs.argument.mismatch=Typvariable(n) {0} nicht ableitbar\n(nicht \u00FCbereinstimmende varargs, {1}) + +# 0: type, 1: list of type +compiler.misc.inferred.do.not.conform.to.upper.bounds=Abgeleiteter Typ entspricht nicht den oberen Grenzwerten\nAbgeleitet: {0}\nObere Grenzwerte: {1} + +# 0: type, 1: list of type +compiler.misc.inferred.do.not.conform.to.lower.bounds=Abgeleiteter Typ entspricht nicht den unteren Grenzwerten\nAbgeleitet: {0}\nUntere Grenzwerte: {1} + +# 0: type, 1: list of type +compiler.misc.inferred.do.not.conform.to.eq.bounds=Abgeleiteter Typ entspricht nicht den Gleichheits-Constraints\nAbgeleitet: {0}\nGleichheits-Constraint(s): {1} + +# 0: symbol +compiler.misc.diamond={0}<> + +# 0: type +compiler.misc.diamond.non.generic="<>" kann nicht mit der nicht generischen Klasse {0} verwendet werden + +# 0: list of type, 1: message segment +compiler.misc.diamond.invalid.arg=Typargument {0}, das f\u00FCr {1} abgeleitet wurde, ist in diesem Kontext nicht zul\u00E4ssig\nDas abgeleitete Argument kann nicht im Signaturattribut ausgedr\u00FCckt werden + +# 0: list of type, 1: message segment +compiler.misc.diamond.invalid.args=Typargumente {0}, die f\u00FCr {1} abgeleitet wurden, sind in diesem Kontext nicht zul\u00E4ssig\nAbgeleitete Argumente k\u00F6nnen nicht im Signaturattribut ausgedr\u00FCckt werden + +# 0: type +compiler.misc.diamond.and.explicit.params="<>" kann nicht mit expliziten Typparametern f\u00FCr Konstruktor verwendet werden + +compiler.misc.mref.infer.and.explicit.params=Raw-Konstruktorreferenz kann nicht mit expliziten Typparametern f\u00FCr Konstruktor verwendet werden + +# 0: type, 1: list of type +compiler.misc.explicit.param.do.not.conform.to.bounds=Explizites Typargument {0} entspricht nicht den deklarierten Grenzwerten {1} + +compiler.misc.arg.length.mismatch=Liste der tats\u00E4chlichen Argumente hat eine andere L\u00E4nge als die der formalen Argumente + +# 0: string +compiler.misc.wrong.number.type.args=Falsche Anzahl Typargumente. {0} erforderlich + +# 0: message segment +compiler.misc.no.conforming.assignment.exists=Keine \u00FCbereinstimmenden Argumente, {0} + +# 0: message segment +compiler.misc.varargs.argument.mismatch=Keine \u00FCbereinstimmenden varargs; {0} + +##### + +# 0: symbol or type, 1: file name +compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file=Auf Auxiliary-Klasse {0} in {1} darf nicht von au\u00DFerhalb der eigenen Quelldatei zugegriffen werden + +## The first argument ({0}) is a "kindname". +# 0: kind name, 1: symbol, 2: symbol +compiler.err.abstract.cant.be.accessed.directly={0} {1} in {2} ist abstrakt und kann nicht direkt aufgerufen werden + +## The first argument ({0}) is a "kindname". +# 0: symbol kind, 1: symbol +compiler.err.non-static.cant.be.ref={0} {1} ist nicht statisch und kann nicht aus einem statischen Kontext referenziert werden + +# 0: symbol kind, 1: symbol +compiler.misc.bad.static.method.in.unbound.lookup=Unerwartete statische {0} {1} in ungebundenem Lookup gefunden + +# 0: symbol kind, 1: symbol +compiler.misc.bad.instance.method.in.unbound.lookup=Unerwartete Instanz {0} {1} in ungebundenem Lookup gefunden + +# 0: symbol kind, 1: symbol +compiler.misc.bad.static.method.in.bound.lookup=Unerwartete statische {0} {1} in gebundenem Lookup gefunden + +## Both arguments ({0}, {1}) are "kindname"s. {0} is a comma-separated list +## of kindnames (the list should be identical to that provided in source. +# 0: set of kind name, 1: set of kind name +compiler.err.unexpected.type=Unerwarteter Typ\nErforderlich: {0}\nErmittelt: {1} + +compiler.err.unexpected.lambda=Hier wird kein Lambda-Ausdruck erwartet + +compiler.err.unexpected.mref=Hier wird keine Methodenreferenz erwartet + +## The first argument {0} is a "kindname" (e.g. 'constructor', 'field', etc.) +## The second argument {1} is the non-resolved symbol +## The third argument {2} is a list of type parameters (non-empty if {1} is a method) +## The fourth argument {3} is a list of argument types (non-empty if {1} is a method) +# 0: kind name, 1: name, 2: unused, 3: unused +compiler.err.cant.resolve=Symbol nicht gefunden\nSymbol: {0} {1} + +# 0: kind name, 1: name, 2: unused, 3: list of type +compiler.err.cant.resolve.args=Symbol nicht gefunden\nSymbol: {0} {1}({3}) + +# 0: kind name, 1: name, 2: unused, 3: list of type +compiler.misc.cant.resolve.args=Symbol nicht gefunden\nSymbol: {0} {1}({3}) + +# 0: kind name, 1: name, 2: list of type, 3: list of type +compiler.err.cant.resolve.args.params=Symbol nicht gefunden\nSymbol: {0} <{2}>{1}({3}) + +## arguments from {0} to {3} have the same meaning as above +## The fifth argument {4} is a location subdiagnostic (see below) +# 0: kind name, 1: name, 2: unused, 3: unused, 4: message segment +compiler.err.cant.resolve.location=Symbol nicht gefunden\nSymbol: {0} {1}\nOrt: {4} + +# 0: kind name, 1: name, 2: unused, 3: list of type, 4: message segment +compiler.err.cant.resolve.location.args=Symbol nicht gefunden\nSymbol: {0} {1}({3})\nOrt: {4} + +# 0: kind name, 1: name, 2: list of type, 3: list, 4: message segment +compiler.err.cant.resolve.location.args.params=Symbol nicht gefunden\nSymbol: {0} <{2}>{1}({3})\nOrt: {4} + +### Following are replicated/used for method reference diagnostics + +# 0: kind name, 1: name, 2: unused, 3: list of type, 4: message segment +compiler.misc.cant.resolve.location.args=Symbol nicht gefunden\nSymbol: {0} {1}({3})\nOrt: {4} + +# 0: kind name, 1: name, 2: list of type, 3: list, 4: message segment +compiler.misc.cant.resolve.location.args.params=Symbol nicht gefunden\nSymbol: {0} <{2}>{1}({3})\nOrt: {4} + +##a location subdiagnostic is composed as follows: +## The first argument {0} is the location "kindname" (e.g. 'constructor', 'field', etc.) +## The second argument {1} is the location name +## The third argument {2} is the location type (only when {1} is a variable name) + +# 0: kind name, 1: type or symbol, 2: unused +compiler.misc.location={0} {1} + +# 0: kind name, 1: symbol, 2: type +compiler.misc.location.1={0} {1} von Typ {2} + +## The following are all possible string for "kindname". +## They should be called whatever the JLS calls them after it been translated +## to the appropriate language. +# compiler.misc.kindname.constructor=\ +# static member +compiler.misc.kindname.annotation=@interface + +compiler.misc.kindname.constructor=Konstruktor + +compiler.misc.kindname.enum=Enumeration + +compiler.misc.kindname.interface=Schnittstelle + +compiler.misc.kindname.static=statisch + +compiler.misc.kindname.type.variable=Typvariable + +compiler.misc.kindname.type.variable.bound=Grenzwert von Typvariable + +compiler.misc.kindname.variable=Variable + +compiler.misc.kindname.value=Wert + +compiler.misc.kindname.method=Methode + +compiler.misc.kindname.class=Klasse + +compiler.misc.kindname.package=Package + +compiler.misc.kindname.module=Modul + +compiler.misc.kindname.static.init=statischer Initializer + +compiler.misc.kindname.instance.init=Instanz-Initializer + +compiler.misc.kindname.record.component=Datensatzkomponente + +compiler.misc.kindname.record=Datensatz + +##### + +compiler.misc.no.args=keine Argumente + +# 0: message segment +compiler.err.override.static={0}\nAu\u00DFer Kraft setzende Methode ist statisch + +# 0: message segment, 1: set of flag +compiler.err.override.meth={0}\nAu\u00DFer Kraft gesetzte Methode ist {1} + +# 0: message segment, 1: type +compiler.err.override.meth.doesnt.throw={0}\nAu\u00DFer Kraft gesetzte Methode l\u00F6st nicht {1} aus + +# In the following string {1} is a space separated list of Java Keywords, as +# they would have been declared in the source code +# 0: message segment, 1: set of flag or string +compiler.err.override.weaker.access={0}\nVersuch, niedrigere Zugriffsberechtigungen zuzuweisen. War {1} + +# 0: message segment, 1: type, 2: type +compiler.err.override.incompatible.ret={0}\nR\u00FCckgabetyp {1} ist nicht mit {2} kompatibel + +# 0: message segment, 1: type, 2: type +compiler.warn.override.unchecked.ret={0}\nR\u00FCckgabetyp erfordert eine nicht gepr\u00FCfte Konvertierung von {1} in {2} + +# 0: message segment, 1: type +compiler.warn.override.unchecked.thrown={0}\nAu\u00DFer Kraft gesetzte Methode l\u00F6st nicht {1} aus + +# 0: symbol +compiler.warn.override.equals.but.not.hashcode=Klasse {0} setzt Gleichwertige au\u00DFer Kraft. hashCode-Methode wird aber weder von der Klasse noch einer Superklasse au\u00DFer Kraft gesetzt + +## The following are all possible strings for the first argument ({0}) of the +## above strings. +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.cant.override={0} in {1} kann nicht {2} in {3} au\u00DFer Kraft setzen + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.cant.hide={0} in {1} kann nicht {2} in {3} ausblenden + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.cant.implement={0} in {1} kann nicht {2} in {3} implementieren + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.clashes.with={0} in {1} steht mit {2} in {3} in Konflikt + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.unchecked.override={0} in {1} setzt {2} in {3} au\u00DFer Kraft + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.unchecked.implement={0} in {1} implementiert {2} in {3} + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.unchecked.clash.with={0} in {1} setzt {2} in {3} au\u00DFer Kraft + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.varargs.override={0} in {1} setzt {2} in {3} au\u00DFer Kraft + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.varargs.implement={0} in {1} implementiert {2} in {3} + +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.varargs.clash.with={0} in {1} setzt {2} in {3} au\u00DFer Kraft + +# 0: kind name, 1: symbol, 2: symbol, 3: message segment +compiler.misc.inapplicable.method={0} {1}.{2} ist nicht anwendbar\n({3}) + +######################################## +# Diagnostics for language feature changes. +# Such diagnostics have a common template which can be customized by using a feature +# diagnostic fragment (one of those given below). +######################################## + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.err.feature.not.supported.in.source={0} wird in -source {1} nicht unterst\u00FCtzt\n(Verwenden Sie -source {2} oder h\u00F6her, um {0} zu aktivieren) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.err.feature.not.supported.in.source.plural={0} werden in -source {1} nicht unterst\u00FCtzt\n(Verwenden Sie -source {2} oder h\u00F6her, um {0} zu aktivieren) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.misc.feature.not.supported.in.source={0} wird in -source {1} nicht unterst\u00FCtzt\n(Verwenden Sie -source {2} oder h\u00F6her, um {0} zu aktivieren) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.misc.feature.not.supported.in.source.plural={0} werden in -source {1} nicht unterst\u00FCtzt\n(Verwenden Sie -source {2} oder h\u00F6her, um {0} zu aktivieren) + +# 0: message segment (feature) +compiler.err.preview.feature.disabled={0} ist ein Vorschaufeature, das standardm\u00E4\u00DFig deaktiviert ist.\n(Verwenden Sie --enable-preview, um {0} zu aktivieren) + +# 0: message segment (feature) +compiler.err.preview.feature.disabled.plural={0} sind ein Vorschaufeature, das standardm\u00E4\u00DFig deaktiviert ist.\n(Verwenden Sie --enable-preview, um {0} zu aktivieren) + +# 0: file object (classfile), 1: string (expected version) +compiler.err.preview.feature.disabled.classfile=Klassendatei f\u00FCr {0} verwendet Vorschaufeatures von Java SE {1}.\n(Verwenden Sie --enable-preview, um das Laden von Klassendateien mit Vorschaufeatures zu erm\u00F6glichen) + +# 0: message segment (feature) +compiler.warn.preview.feature.use={0} ist ein Vorschaufeature, das in einem zuk\u00FCnftigen Release entfernt werden kann. + +# 0: message segment (feature) +compiler.warn.preview.feature.use.plural={0} sind ein Vorschaufeature, das in einem zuk\u00FCnftigen Release entfernt werden kann. + +# 0: file object (classfile), 1: string (expected version) +compiler.warn.preview.feature.use.classfile=Klassendatei f\u00FCr {0} verwendet Vorschaufeatures von Java SE {1}. + + +compiler.misc.feature.modules=Module + +compiler.misc.feature.diamond.and.anon.class="<>" mit anonymen inneren Klassen + +compiler.misc.feature.var.in.try.with.resources=Variablen in try-with-resources + +compiler.misc.feature.type.annotations=Typannotationen + +compiler.misc.feature.annotations.after.type.params=Annotationen nach Methodentypparametern + +compiler.misc.feature.repeatable.annotations=Wiederholte Annotationen + +compiler.misc.feature.diamond=Rautenoperator + +compiler.misc.feature.lambda=Lambda-Ausdr\u00FCcke + +compiler.misc.feature.method.references=Methodenreferenzen + +compiler.misc.feature.default.methods=Standardmethoden + +compiler.misc.feature.intersection.types.in.cast=Schnittmengentypen + +compiler.misc.feature.static.intf.methods=Statische Schnittstellenmethoden + +compiler.misc.feature.static.intf.method.invoke=Aufrufe statischer Schnittstellenmethoden + +compiler.misc.feature.private.intf.methods=Private Schnittstellenmethoden + +compiler.misc.feature.text.blocks=Textbl\u00F6cke + +compiler.misc.feature.multiple.case.labels=Mehrere CASE-Labels + +compiler.misc.feature.switch.rules=Switch-Regeln + +compiler.misc.feature.switch.expressions=Switch-Ausdr\u00FCcke + +compiler.misc.feature.var.syntax.in.implicit.lambda=var-Syntax in impliziten Lambdas + +compiler.misc.feature.pattern.matching.instanceof=Musterabgleich in instanceof + +compiler.misc.feature.reifiable.types.instanceof=Reifizierbare Typen in instanceof + +compiler.misc.feature.records=Datens\u00E4tze + +compiler.misc.feature.sealed.classes=Verschl\u00FCsselte Klassen + +compiler.misc.feature.case.null=Null in Switch Cases + +compiler.misc.feature.pattern.switch=Muster in Switch-Anweisungen + +compiler.warn.underscore.as.identifier=Ab Release 9 ist "_" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden + +compiler.err.underscore.as.identifier=Ab Release 9 ist "_" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden + +compiler.err.underscore.as.identifier.in.lambda="_" als ID verwendet\n("_" darf nicht als ID f\u00FCr Lambda-Parameter verwendet werden) + +compiler.err.enum.as.identifier=Ab Release 5 ist "enum" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden + +compiler.err.assert.as.identifier=Ab Release 1.4 ist "assert" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden + +# TODO 308: make a better error message +compiler.err.this.as.identifier=Ab Release 8 ist "this" nur als Parametername f\u00FCr den Empf\u00E4ngertyp zul\u00E4ssig.\nDas muss der erste Parameter sein und darf kein Lambda-Parameter sein + +compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class=receiver-Parameter nicht f\u00FCr Konstruktor der obersten Klasse anwendbar + +# TODO 308: make a better error message +# 0: annotation +compiler.err.cant.type.annotate.scoping.1=Scoping-Konstrukt kann nicht mit type-use-Annotation versehen werden: {0} + +# TODO 308: make a better error message +# 0: list of annotation +compiler.err.cant.type.annotate.scoping=Scoping-Konstrukt kann nicht mit type-use-Annotationen versehen werden: {0} + +# 0: type, 1: type +compiler.err.incorrect.receiver.name=Der Empf\u00E4ngername stimmt nicht mit dem einschlie\u00DFenden Klassentyp \u00FCberein\nErforderlich: {0}\nErmittelt: {1} + +# 0: type, 1: type +compiler.err.incorrect.receiver.type=Der Empf\u00E4ngertyp stimmt nicht mit dem einschlie\u00DFenden Klassentyp \u00FCberein\nErforderlich: {0}\nErmittelt: {1} + +# 0: type, 1: type +compiler.err.incorrect.constructor.receiver.type=Der Empf\u00E4ngertyp stimmt nicht mit dem einschlie\u00DFenden \u00E4u\u00DFeren Klassentyp \u00FCberein\nErforderlich: {0}\nErmittelt: {1} + +# 0: type, 1: type +compiler.err.incorrect.constructor.receiver.name=Der Empf\u00E4ngername stimmt nicht mit dem einschlie\u00DFenden \u00E4u\u00DFeren Klassentyp \u00FCberein\nErforderlich: {0}\nErmittelt: {1} + +compiler.err.no.annotations.on.dot.class=Keine Annotationen im Typ eines Klassenliterals zul\u00E4ssig + +######################################## +# Diagnostics for verbose resolution +# used by Resolve (debug only) +######################################## + +# 0: number, 1: symbol, 2: unused +compiler.misc.applicable.method.found=#{0} anwendbare Methode gefunden: {1} + +# 0: number, 1: symbol, 2: message segment +compiler.misc.applicable.method.found.1=#{0} anwendbare Methode gefunden: {1}\n({2}) + +# 0: number, 1: symbol, 2: message segment +compiler.misc.not.applicable.method.found=#{0} nicht anwendbare Methode gefunden: {1}\n({2}) + +# 0: type +compiler.misc.partial.inst.sig=Teilweise instanziiert in: {0} + +# 0: name, 1: symbol, 2: number, 3: string (method resolution phase), 4: list of type or message segment, 5: list of type or message segment +compiler.note.verbose.resolve.multi=Methode {0} wird in Typ {1} als Kandidat {2} aufgel\u00F6st\nPhase: {3}\nMit Istwerten: {4}\nMit type-args: {5}\nKandidaten: + +# 0: name, 1: symbol, 2: unused, 3: string (method resolution phase), 4: list of type or message segment, 5: list of type or message segment +compiler.note.verbose.resolve.multi.1=Fehlerhafte Aufl\u00F6sung f\u00FCr Methode {0} in Typ {1}\nPhase: {3}\nMit Istwerten: {4}\nMit type-args: {5}\nKandidaten: + +# 0: symbol, 1: type, 2: type +compiler.note.deferred.method.inst=Instanziierung von Methode {0} verz\u00F6gert\nInstanziierte Signatur: {1}\ntarget-type: {2} + +######################################## +# Diagnostics for lambda deduplication +# used by LambdaToMethod (debug only) +######################################## + +# 0: symbol +compiler.note.verbose.l2m.deduplicate=Lambda-Implementierungsmethode {0} wird dedupliziert + +######################################## +# Diagnostics for method reference search +# results used by Resolve (debug only) +######################################## + +# 0: fragment, 1: string, 2: number +compiler.note.method.ref.search.results.multi={0} Suchergebnisse f\u00FCr {1}, mit spezifischsten {2}\nAnwendbare Kandidaten: + +# 0: number, 1: fragment, 2: symbol +compiler.misc.applicable.method.found.2=#{0} anwendbare Methode gefunden: {1} {2} + +# 0: number, 1: fragment, 2: symbol, 3: message segment +compiler.misc.applicable.method.found.3=#{0} anwendbare Methode gefunden: {1} {2}\n({3}) + +compiler.misc.static=statisch + +compiler.misc.non.static=nicht statisch + +compiler.misc.bound=gebunden + +compiler.misc.unbound=ungebunden + +######################################## +# Diagnostics for where clause implementation +# used by the RichDiagnosticFormatter. +######################################## + +compiler.misc.type.null= + +# X#n (where n is an int id) is disambiguated tvar name +# 0: name, 1: number +compiler.misc.type.var={0}#{1} + +# CAP#n (where n is an int id) is an abbreviation for 'captured type' +# 0: number +compiler.misc.captured.type=CAP#{0} + +# (where n is an int id) is an abbreviation for 'intersection type' +# 0: number +compiler.misc.intersection.type=INT#{0} + +# where clause for captured type: contains upper ('extends {1}') and lower +# ('super {2}') bound along with the wildcard that generated this captured type ({3}) +# 0: type, 1: type, 2: type, 3: type +compiler.misc.where.captured={0} erweitert {1} Super: {2} aus Erfassung von {3} + +# compact where clause for captured type: contains upper ('extends {1}') along +# with the wildcard that generated this captured type ({3}) +# 0: type, 1: type, 2: unused, 3: type +compiler.misc.where.captured.1={0} erweitert {1} aus Erfassung von {3} + +# where clause for type variable: contains upper bound(s) ('extends {1}') along with +# the kindname ({2}) and location ({3}) in which the typevar has been declared +# 0: type, 1: list of type, 2: symbol kind, 3: symbol +compiler.misc.where.typevar={0} erweitert {1}, deklariert in {2} {3} + +# compact where clause for type variable: contains the kindname ({2}) and location ({3}) +# in which the typevar has been declared +# 0: type, 1: list of type, 2: symbol kind, 3: symbol +compiler.misc.where.typevar.1={0} deklariert in {2} {3} + +# where clause for fresh type variable: contains upper bound(s) ('extends {1}'). +# Since a fresh type-variable is synthetic - there's no location/kindname here. +# 0: type, 1: list of type +compiler.misc.where.fresh.typevar={0} erweitert {1} + +# where clause for type variable: contains all the upper bound(s) ('extends {1}') +# of this intersection type +# 0: type, 1: list of type +compiler.misc.where.intersection={0} erweitert {1} + +### Where clause headers ### +compiler.misc.where.description.captured=Dabei ist {0} eine neue Typvariable: + +# 0: set of type +compiler.misc.where.description.typevar=Dabei ist {0} eine Typvariable: + +# 0: set of type +compiler.misc.where.description.intersection=Dabei ist {0} ein Schnittmengentyp: + +# 0: set of type +compiler.misc.where.description.captured.1=Dabei sind {0} neue Typvariablen: + +# 0: set of type +compiler.misc.where.description.typevar.1=Dabei sind {0} Typvariablen: + +# 0: set of type +compiler.misc.where.description.intersection.1=Dabei sind {0} Schnittmengentypen: + +### +# errors related to doc comments + +compiler.err.dc.bad.entity=Ung\u00FCltige HTML-Entity + +compiler.err.dc.bad.inline.tag=Falsche Verwendung von Inlinetag + +compiler.err.dc.identifier.expected=ID erwartet + +compiler.err.dc.malformed.html=Nicht wohlgeformte HTML + +compiler.err.dc.missing.semicolon=Semikolon fehlt + +compiler.err.dc.no.content=kein Inhalt + +compiler.err.dc.no.tag.name=Kein Tagname nach "@" + +compiler.err.dc.gt.expected=">" erwartet + +compiler.err.dc.ref.bad.parens=Unerwarteter Text nach Klammer + +compiler.err.dc.ref.syntax.error=Syntaxfehler in Referenz + +compiler.err.dc.ref.unexpected.input=Unerwarteter Text + +compiler.err.dc.unexpected.content=Unerwarteter Inhalt + +compiler.err.dc.unterminated.inline.tag=Nicht abgeschlossenes Inlinetag + +compiler.err.dc.unterminated.signature=Nicht abgeschlossene Signatur + +compiler.err.dc.unterminated.string=Nicht abgeschlossene Zeichenfolge + +compiler.err.dc.ref.annotations.not.allowed=Annotationen nicht zul\u00E4ssig + +### +# errors related to modules + +compiler.err.expected.module="module" erwartet + +# 0: symbol +compiler.err.module.not.found=Modul nicht gefunden: {0} + +# 0: symbol +compiler.warn.module.not.found=Modul nicht gefunden: {0} + +compiler.err.too.many.modules=Zu viele Moduldeklarationen gefunden + +compiler.err.module.not.found.on.module.source.path=Modul nicht in Modulquellpfad gefunden + +compiler.err.not.in.module.on.module.source.path=Nicht in einem Modul im Modulquellpfad + +# 0: symbol +compiler.err.duplicate.module=Doppeltes Modul: {0} + +# 0: symbol +compiler.err.duplicate.requires=Doppelte "requires": {0} + +# 0: symbol +compiler.err.conflicting.exports=Doppelte oder unvereinbare Exporte: {0} + +# 0: symbol +compiler.err.conflicting.opens=Doppelte oder unvereinbare "opens": {0} + +# 0: symbol +compiler.err.conflicting.exports.to.module=Doppelte oder unvereinbare Exporte in Modul: {0} + +# 0: symbol +compiler.err.conflicting.opens.to.module=Doppelte oder unvereinbare "opens" in Modul: {0} + +compiler.err.no.opens.unless.strong="opens" nur in starken Modulen zul\u00E4ssig + +# 0: symbol +compiler.err.repeated.provides.for.service=Mehrere "provides" f\u00FCr Service {0} + +# 0: symbol, 1: symbol +compiler.err.duplicate.provides=Doppelte "provides": Service {0}, Implementierung {1} + +# 0: symbol +compiler.err.duplicate.uses=Doppelte Verwendungen: {0} + +# 0: symbol +compiler.err.service.implementation.is.abstract=Die Serviceimplementierung ist eine abstrakte Klasse: {0} + +compiler.err.service.implementation.must.be.subtype.of.service.interface=Der Serviceimplementierungstyp muss ein Subtyp des Serviceschnittstellentyps sein oder eine \u00F6ffentliche statische no-args-Methode namens "provider" aufweisen, die die Serviceimplementierung zur\u00FCckgibt + +compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface=Der R\u00FCckgabetyp der "provider"-Methode muss ein Subtyp des Serviceschnittstellentyps sein + +# 0: symbol +compiler.err.service.implementation.is.inner=Die Serviceimplementierung ist eine innere Klasse: {0} + +# 0: symbol +compiler.err.service.definition.is.enum=Die Servicedefinition ist eine Enumeration: {0} + +# 0: symbol +compiler.err.service.implementation.doesnt.have.a.no.args.constructor=Die Serviceimplementierung hat keinen Standardkonstruktor: {0} + +# 0: symbol +compiler.err.service.implementation.no.args.constructor.not.public=Der "no arguments"-Konstruktor der Serviceimplementierung ist nicht \u00F6ffentlich: {0} + +# 0: symbol +compiler.err.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} + +# 0: symbol +compiler.warn.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} + +compiler.err.no.output.dir=Kein Klassenausgabeverzeichnis angegeben + +compiler.err.unnamed.pkg.not.allowed.named.modules=Unbenanntes Package ist in benannten Modulen nicht zul\u00E4ssig + +# 0: name, 1: name +compiler.err.module.name.mismatch=Modulname {0} stimmt nicht mit dem erwarteten Namen {1} \u00FCberein + +# 0: name, 1: name +compiler.misc.module.name.mismatch=Modulname {0} stimmt nicht mit dem erwarteten Namen {1} \u00FCberein + +# 0: name +compiler.err.module.non.zero.opens=Bei ge\u00F6ffnetem Modul {0} ist opens_count ungleich Null + +# 0: name +compiler.misc.module.non.zero.opens=Bei ge\u00F6ffnetem Modul {0} ist opens_count ungleich Null + +compiler.err.module.decl.sb.in.module-info.java=Moduldeklarationen m\u00FCssen in einer Datei namens module-info.java vorhanden sein + +# 0: set of string +compiler.err.too.many.patched.modules=Zu viele gepatchte Module ({0}). Verwenden Sie --module-source-path + +# 0: name, 1: name +compiler.err.file.patched.and.msp=Datei sowohl von --patch-module als auch von --module-source-path zug\u00E4nglich, geh\u00F6rt aber in jedem Pfad zu einem anderen Modul: {0}, {1} + +compiler.err.processorpath.no.processormodulepath=Unzul\u00E4ssige Kombination aus -processorpath und --processor-module-path + +# 0: symbol +compiler.err.package.in.other.module=Package ist in einem anderen Modul vorhanden: {0} + +# 0: symbol, 1: name, 2: symbol, 3: symbol +compiler.err.package.clash.from.requires=Modul {0} liest Package {1} sowohl aus {2} als auch aus {3} + +# 0: name, 1: symbol, 2: symbol +compiler.err.package.clash.from.requires.in.unnamed=Das unbenannte Modul liest Package {0} sowohl aus {1} als auch aus {2} + +# 0: string +compiler.err.module.not.found.in.module.source.path=Modul {0} nicht in Modulquellpfad gefunden + +compiler.err.output.dir.must.be.specified.with.dash.m.option=Klassenausgabeverzeichnis muss angegeben werden, wenn die Option -m verwendet wird + +compiler.err.modulesourcepath.must.be.specified.with.dash.m.option=Modulquellpfad muss angegeben werden, wenn die Option -m verwendet wird + +# 0: symbol +compiler.err.service.implementation.not.in.right.module=Serviceimplementierung muss in demselben Modul wie die provides-Direktive definiert werden + +# 0: symbol +compiler.err.cyclic.requires=Zyklische Abh\u00E4ngigkeit mit {0} + +# 0: fragment, 1: name +compiler.err.duplicate.module.on.path=Doppeltes Modul in {0}\nModul in {1} + +# 0: option name, 1: string +compiler.warn.bad.name.for.option=Ung\u00FCltiger Name im Wert f\u00FCr {0}-Option: "{1}" + +# 0: option name, 1: string +compiler.err.bad.name.for.option=Ung\u00FCltiger Name im Wert f\u00FCr {0}-Option: "{1}" + +# 0: option name, 1: symbol +compiler.warn.module.for.option.not.found=Modulname in {0}-Option nicht gefunden: {1} + +compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH kann nur beim Kompilieren des unbenannten Moduls oder beim Kompilieren im Kontext eines automatischen Moduls verwendet werden + +# 0: symbol +compiler.err.add.exports.with.release=Export eines Packages aus Systemmodul {0} ist mit --release nicht zul\u00E4ssig + +# 0: symbol +compiler.err.add.reads.with.release=Hinzuf\u00FCgen von Lese-Edges f\u00FCr Systemmodul {0} ist mit --release nicht zul\u00E4ssig + +compiler.warn.addopens.ignored=--add-opens hat zur Kompilierungszeit keine Auswirkungen + +compiler.misc.locn.module_source_path=Modulquellpfad + +compiler.misc.locn.upgrade_module_path=Upgrademodulpfad + +compiler.misc.locn.system_modules=Systemmodule + +compiler.misc.locn.module_path=Anwendungsmodulpfad + +compiler.misc.cant.resolve.modules=Module k\u00F6nnen nicht aufgel\u00F6st werden + +compiler.misc.bad.requires.flag=Ung\u00FCltiges requires-Kennzeichen: {0} + +# 0: string +compiler.err.invalid.module.specifier=Modulbezeichner nicht zul\u00E4ssig: {0} + +# 0: symbol +compiler.warn.service.provided.but.not.exported.or.used=Serviceschnittstelle angegeben, aber nicht exportiert oder verwendet + +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible={0} {1} in Modul {2} ist nicht zug\u00E4nglich f\u00FCr Clients, die dieses Modul ben\u00F6tigen +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.unexported={0} {1} in Modul {2} wird nicht exportiert +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.not.required.transitive={0} {1} in Modul {2} wird nicht indirekt mit "requires transitive" exportiert +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.unexported.qualified={0} {1} in Modul {2} ist m\u00F6glichweise nicht f\u00FCr alle Clients, die dieses Modul ben\u00F6tigen, sichtbar + +### +# errors related to options + +# 0: string, 1: string +compiler.err.illegal.argument.for.option=Unzul\u00E4ssiges Argument f\u00FCr {0}: {1} + +compiler.err.match.binding.exists=Unzul\u00E4ssiger Versuch, ein vorhandenes \u00DCbereinstimmungs-Binding neu zu definieren + +compiler.err.switch.case.unexpected.statement=Unerwartete Anweisung in Case. Ausdruck, Block oder throw-Anweisung erwartet + +compiler.err.switch.mixing.case.types=Unterschiedliche Case-Typen im Switch verwendet + +### +# errors related to sealed classes + +# permits clause +# 0: fragment +compiler.err.invalid.permits.clause=Ung\u00FCltige PERMITS-Klausel\n({0}) + +# 0: string +compiler.misc.class.is.not.sealed={0} muss verschl\u00FCsselt sein + +# 0: type +compiler.misc.is.a.type.variable=Darf keine Typvariablen enthalten: {0} + +# 0: type +compiler.misc.is.duplicated=Darf keine Duplikate enthalten: {0} + +# 0: type +compiler.misc.doesnt.extend.sealed=Unterklasse {0} muss verschl\u00FCsselte Klasse erweitern + +compiler.misc.must.not.be.same.class=Unzul\u00E4ssige Selbstreferenz in PERMITS-Klausel + +# 0: type +compiler.misc.must.not.be.supertype=Unzul\u00E4ssige Referenz zu Supertyp {0} + +# other sealed types related errors + +compiler.err.sealed.class.must.have.subclasses=Verschl\u00FCsselte Klasse muss Unterklassen aufweisen + +# errors in subclasses of sealed classes +# 0: symbol +compiler.err.cant.inherit.from.sealed=Klasse darf nicht verschl\u00FCsselte Klasse erweitern: {0} (da diese nicht in der "permits"-Klausel enthalten ist) + +# 0: symbol +compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package=Klasse {0} in unbenanntem Modul darf keine verschl\u00FCsselte Klasse in einem anderen Package erweitern + +# 0: symbol, 1: symbol +compiler.err.class.in.module.cant.extend.sealed.in.diff.module=Klasse {0} in Modul {1} darf keine verschl\u00FCsselte Klasse in einem anderen Modul erweitern + +# 0: symbol +compiler.err.non.sealed.with.no.sealed.supertype=Modifikator "non-sealed" ist hier nicht zul\u00E4ssig\n(Klasse {0} hat keine verschl\u00FCsselten Supertypen) + +compiler.err.non.sealed.sealed.or.final.expected=Modifikator "sealed", "non-sealed" oder "final" erwartet + +compiler.err.non.sealed.or.sealed.expected=Modifikator "sealed" oder "non-sealed" erwartet + +compiler.err.sealed.or.non.sealed.local.classes.not.allowed=Lokale Klassen mit "sealed" oder "non-sealed" nicht zul\u00E4ssig + +# 0: fragment +compiler.err.local.classes.cant.extend.sealed=Klassen vom Typ "{0}" d\u00FCrfen keine verschl\u00FCsselten Klassen erweitern +compiler.misc.anonymous=Anonym + +compiler.misc.local=Lokal + +### +# errors related to records + +# record components +compiler.err.record.cant.declare.field.modifiers=Datensatzkomponenten k\u00F6nnen keine Modifikatoren aufweisen + +# 0: symbol +compiler.err.illegal.record.component.name=Unzul\u00E4ssiger Datensatzkomponentenname {0} + +compiler.err.record.component.and.old.array.syntax=Legacy-Arraynotation f\u00FCr Datensatzkomponenten nicht zul\u00E4ssig + +# accessor methods +# 0: symbol, 1: fragment +compiler.err.invalid.accessor.method.in.record=Ung\u00FCltige Accessor-Methode in Datensatz {0}\n({1}) + +compiler.misc.method.must.be.public=Accessor-Methode muss \u00F6ffentlich sein + +# 0: symbol, 1: symbol +compiler.misc.accessor.return.type.doesnt.match=R\u00FCckgabetyp von Accessor-Methode {0} muss mit dem Typ der Datensatzkomponente {1} \u00FCbereinstimmen + +compiler.misc.accessor.method.cant.throw.exception=Throws-Klausel f\u00FCr Accessor-Methode nicht zul\u00E4ssig + +compiler.misc.accessor.method.must.not.be.generic=Accessor-Methode darf nicht generisch sein + +compiler.misc.accessor.method.must.not.be.static=Accessor-Methode darf nicht statisch sein + +# canonical constructors +# 0: fragment, 1: name, 2: fragment +compiler.err.invalid.canonical.constructor.in.record=Ung\u00FCltiger Konstruktor vom Typ {0} in Datensatz {1}\n({2}) + +compiler.misc.canonical=Kanonisch + +compiler.misc.compact=Kompakt + +# 0: fragment +compiler.misc.throws.clause.not.allowed.for.canonical.constructor=Throws-Klausel f\u00FCr Konstruktor des Typs {0} nicht zul\u00E4ssig + +compiler.misc.canonical.with.name.mismatch=Ung\u00FCltige Parameternamen in kanonischem Konstruktor + +compiler.misc.canonical.cant.have.return.statement=Kompakter Konstruktor darf keine return-Anweisungen verwenden + +compiler.misc.canonical.must.not.declare.type.variables=Kanonischer Konstruktor darf keine Typvariablen deklarieren + +compiler.misc.type.must.be.identical.to.corresponding.record.component.type=Typ und Argumentanzahl m\u00FCssen mit den Werten der entsprechenden Datensatzkomponente \u00FCbereinstimmen +compiler.misc.canonical.must.not.contain.explicit.constructor.invocation=Kanonischer Konstruktor darf keinen expliziten Konstruktoraufruf enthalten + +# 0: set of flag or string +compiler.misc.canonical.must.not.have.stronger.access=Versuch, h\u00F6here Zugriffsberechtigungen zuzuweisen. War {0} + +# other +compiler.err.record.cannot.declare.instance.fields=Felddeklaration muss statisch sein\n(ersetzen Sie unter Umst\u00E4nden das Feld durch eine Datensatzkomponente) + +# 0: symbol +compiler.err.invalid.supertype.record=Klassen k\u00F6nnen {0} nicht direkt erweitern + +# 0: symbol +compiler.err.first.statement.must.be.call.to.another.constructor=Konstruktor ist nicht kanonisch. Daher muss die erste Anweisung einen anderen Konstruktor der Klasse {0} aufrufen + +compiler.err.instance.initializer.not.allowed.in.records=Instanz-Initializer in Datens\u00E4tzen nicht zul\u00E4ssig + +compiler.err.static.declaration.not.allowed.in.inner.classes=Statische Deklarationen in inneren Klassen nicht zul\u00E4ssig + +compiler.err.record.header.expected=Datensatzheader erwartet + +############################################ +# messages previously at javac.properties + +compiler.err.empty.A.argument=-A erfordert ein Argument. Verwenden Sie "-Akey" oder "-Akey=value" + +# 0: string +compiler.err.invalid.A.key=Schl\u00FCssel in Annotationsprozessoroption "{0}" ist keine durch Punkt getrennte ID-Sequenz + +# 0: string +compiler.err.invalid.flag=Ung\u00FCltiges Kennzeichen: {0} + +compiler.err.profile.bootclasspath.conflict=Optionen "profile" und "bootclasspath" k\u00F6nnen nicht zusammen verwendet werden + +# 0: string +compiler.err.invalid.profile=Ung\u00FCltiges Profil: {0} + +# 0: string +compiler.err.invalid.target=Ung\u00FCltiges Zielrelease: {0} + +# 0: option name, 1: target +compiler.err.option.not.allowed.with.target=Option {0} mit Ziel {1} nicht zul\u00E4ssig + +# 0: string +compiler.err.option.too.many=Option {0} kann nur einmal angegeben werden + +compiler.err.no.source.files=Keine Quelldateien + +compiler.err.no.source.files.classes=Keine Quelldateien oder Klassennamen + +# 0: string +compiler.err.req.arg={0} erfordert ein Argument + +# 0: string +compiler.err.invalid.source=Ung\u00FCltiges Quellrelease: {0} + +# 0: string, 1: string +compiler.err.error.writing.file=Fehler beim Schreiben von {0}. {1} + +compiler.err.sourcepath.modulesourcepath.conflict=--source-path und --module-source-path k\u00F6nnen nicht beide angegeben werden + +# 0: string, 1: target +compiler.warn.source.target.conflict=Quellrelease {0} erfordert Zielrelease {1} + +# 0: string, 1: target +compiler.warn.target.default.source.conflict=Zielrelease {0} steht mit Standardquellrelease {1} in Konflikt + +# 0: profile, 1: target +compiler.warn.profile.target.conflict=Profil {0} ist f\u00FCr Zielrelease {1} nicht g\u00FCltig + +# 0: string +compiler.err.file.not.directory=Kein Verzeichnis: {0} + +# 0: object +compiler.err.file.not.file=Keine Datei: {0} + +compiler.err.two.class.loaders.1=javac ist auf mehrere Class Loader aufgeteilt: Pr\u00FCfen Sie die Konfiguration + +# 0: url, 1: url +compiler.err.two.class.loaders.2=javac ist auf mehrere Class Loader aufgeteilt:\nEine Klasse stammt aus Datei {0},\nw\u00E4hrend javac aus {1} stammt + +# 0: string, 1: string +compiler.err.bad.value.for.option=Ung\u00FCltiger Wert f\u00FCr {0}-Option: "{1}" + +# 0: string +compiler.err.no.value.for.option=Kein Wert f\u00FCr {0}-Option + +# 0: string +compiler.err.repeated.value.for.patch.module=--patch-module mehrmals f\u00FCr Modul {0} angegeben + +# 0: string +compiler.err.repeated.value.for.module.source.path=--module-source-path mehrmals f\u00FCr Modul {0} angegeben + +compiler.err.multiple.values.for.module.source.path=--module-source-path mehrmals mit Musterargument angegeben + +# 0: string +compiler.err.unmatched.quote=Alleinstehendes Anf\u00FChrungszeichen in Umgebungsvariable {0} + +# 0: option name +compiler.err.release.bootclasspath.conflict=Option {0} kann nicht zusammen mit --release verwendet werden + +# 0: string +compiler.err.unsupported.release.version=Releaseversion {0} nicht unterst\u00FCtzt + +# 0: string +compiler.err.file.not.found=Datei nicht gefunden: {0} + +# 0: string, 1: source +compiler.err.preview.not.latest=Ung\u00FCltiges Quellrelease {0} mit --enable-preview\n(Vorschausprachfeatures werden nur f\u00FCr Release {1} unterst\u00FCtzt) + +compiler.err.preview.without.source.or.release=--enable-preview muss mit -source oder --release verwendet werden + +# 0: kind name, 1: symbol +compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zuk\u00FCnftigen Release entfernt werden kann. + +compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=Versuch der Synchronisierung f\u00FCr eine Instanz einer wertbasierten Klasse diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 2e071a4059a77fa6a86c6c9c0fd357cebe630292..86c65650c5917a0f6eb6e1edad5a92479b802d2d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -119,7 +119,7 @@ compiler.err.annotation.missing.default.value.1=\u6CE8\u91C8@{0}\u306B\u306F\u89 # 0: type compiler.err.annotation.not.valid.for.type=\u6CE8\u91C8\u306F\u578B{0}\u306E\u8981\u7D20\u306B\u5BFE\u3057\u3066\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 -compiler.err.annotation.type.not.applicable=\u6CE8\u91C8\u578B\u306F\u3053\u306E\u7A2E\u985E\u306E\u5BA3\u8A00\u306B\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 +compiler.err.annotation.type.not.applicable=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306F\u3053\u306E\u7A2E\u985E\u306E\u5BA3\u8A00\u306B\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 # 0: type compiler.err.annotation.type.not.applicable.to.type=\u6CE8\u91C8@{0}\u306F\u3053\u306E\u578B\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306B\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 @@ -263,12 +263,14 @@ compiler.misc.lambda=\u30E9\u30E0\u30C0\u5F0F compiler.misc.inner.cls=\u5185\u90E8\u30AF\u30E9\u30B9 +compiler.misc.guard=\u30AC\u30FC\u30C9 + # 0: type compiler.err.cant.deref={0}\u306F\u9593\u63A5\u53C2\u7167\u3067\u304D\u307E\u305B\u3093 compiler.err.cant.extend.intf.annotation=@interfaces\u3067\u306F''extends''\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 -compiler.err.annotation.decl.not.allowed.here=\u3053\u3053\u3067\u306F\u6CE8\u91C8\u578B\u306E\u5BA3\u8A00\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 +compiler.err.annotation.decl.not.allowed.here=\u3053\u3053\u3067\u306F\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u5BA3\u8A00\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 # 0: symbol compiler.err.cant.inherit.from.final=final {0}\u304B\u3089\u306F\u7D99\u627F\u3067\u304D\u307E\u305B\u3093 @@ -307,7 +309,7 @@ compiler.err.no.superclass={0}\u306B\u306F\u30B9\u30FC\u30D1\u30FC\u30AF\u30E9\u # 0: symbol, 1: type, 2: symbol, 3: type, 4: type compiler.err.concrete.inheritance.conflict={1}\u306E\u30E1\u30BD\u30C3\u30C9{0}\u3068{3}\u306E{2}\u306F\u540C\u3058\u30B7\u30B0\u30CB\u30C1\u30E3\u304B\u3089\u7D99\u627F\u3055\u308C\u3066\u3044\u307E\u3059 -compiler.err.default.allowed.in.intf.annotation.member=\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u6CE8\u91C8\u578B\u306E\u5BA3\u8A00\u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059 +compiler.err.default.allowed.in.intf.annotation.member=\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u5BA3\u8A00\u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059 # 0: symbol compiler.err.doesnt.exist=\u30D1\u30C3\u30B1\u30FC\u30B8{0}\u306F\u5B58\u5728\u3057\u307E\u305B\u3093 @@ -319,7 +321,7 @@ compiler.err.duplicate.annotation.invalid.repeated=\u6CE8\u91C8{0}\u306F\u6709\u compiler.err.duplicate.annotation.member.value=\u6CE8\u91C8@{1}\u306B\u91CD\u8907\u3057\u305F\u8981\u7D20''{0}''\u304C\u3042\u308A\u307E\u3059\u3002 # 0: type -compiler.err.duplicate.annotation.missing.container={0}\u306F\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u578B\u3067\u306F\u3042\u308A\u307E\u305B\u3093 +compiler.err.duplicate.annotation.missing.container={0}\u306F\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 # 0: symbol compiler.err.invalid.repeatable.annotation=\u6CE8\u91C8\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: {0}\u306F\u7121\u52B9\u306A@Repeatable\u6CE8\u91C8\u3067\u6CE8\u91C8\u4ED8\u3051\u3055\u308C\u3066\u3044\u307E\u3059 @@ -334,22 +336,22 @@ compiler.err.invalid.repeatable.annotation.multiple.values={0}\u306F\u6709\u52B9 compiler.err.invalid.repeatable.annotation.invalid.value={0}\u306F\u6709\u52B9\u306A@Repeatable\u3067\u306F\u3042\u308A\u307E\u305B\u3093: \u5024\u8981\u7D20\u304C\u7121\u52B9\u3067\u3059 # 0: symbol or type, 1: type, 2: type -compiler.err.invalid.repeatable.annotation.value.return=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B({0})\u306F\u578B{2}\u306E\u8981\u7D20''value''\u3092\u5BA3\u8A00\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +compiler.err.invalid.repeatable.annotation.value.return=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({0})\u306F\u578B{2}\u306E\u8981\u7D20''value''\u3092\u5BA3\u8A00\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 # 0: symbol or type, 1: symbol -compiler.err.invalid.repeatable.annotation.elem.nondefault=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B{0}\u306B\u306F\u8981\u7D20{1}\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 +compiler.err.invalid.repeatable.annotation.elem.nondefault=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9{0}\u306B\u306F\u8981\u7D20{1}\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 # 0: symbol, 1: string, 2: symbol, 3: string -compiler.err.invalid.repeatable.annotation.retention=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B({0})\u306E\u4FDD\u6709\u304C\u3001\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u578B({2})\u306E\u4FDD\u6709\u3088\u308A\u77ED\u304F\u306A\u3063\u3066\u3044\u307E\u3059 +compiler.err.invalid.repeatable.annotation.retention=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({0})\u306E\u4FDD\u6709\u304C\u3001\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({2})\u306E\u4FDD\u6709\u3088\u308A\u77ED\u304F\u306A\u3063\u3066\u3044\u307E\u3059 # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.not.documented=\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u578B({1})\u306F@Documented\u3067\u3059\u304C\u3001\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B({0})\u306F\u9055\u3044\u307E\u3059 +compiler.err.invalid.repeatable.annotation.not.documented=\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({1})\u306F@Documented\u3067\u3059\u304C\u3001\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({0})\u306F\u9055\u3044\u307E\u3059 # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.not.inherited=\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u578B({1})\u306F@Inherited\u3067\u3059\u304C\u3001\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B({0})\u306F\u9055\u3044\u307E\u3059 +compiler.err.invalid.repeatable.annotation.not.inherited=\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({1})\u306F@Inherited\u3067\u3059\u304C\u3001\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({0})\u306F\u9055\u3044\u307E\u3059 # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.incompatible.target=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u578B({0})\u306F\u3001\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u578B({1})\u3088\u308A\u591A\u304F\u306E\u30BF\u30FC\u30B2\u30C3\u30C8\u306B\u9069\u7528\u3055\u308C\u307E\u3059 +compiler.err.invalid.repeatable.annotation.incompatible.target=\u5305\u542B\u3059\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({0})\u306F\u3001\u7E70\u8FD4\u3057\u53EF\u80FD\u306A\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9({1})\u3088\u308A\u591A\u304F\u306E\u30BF\u30FC\u30B2\u30C3\u30C8\u306B\u9069\u7528\u3055\u308C\u307E\u3059 # 0: symbol compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\u30B3\u30F3\u30C6\u30CA{0}\u306F\u542B\u307E\u308C\u3066\u3044\u308B\u8981\u7D20\u3068\u540C\u6642\u306B\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093 @@ -368,8 +370,21 @@ compiler.err.same.binary.name=\u30AF\u30E9\u30B9: {0}\u3068{1}\u306E\u30D0\u30A4 compiler.err.duplicate.case.label=case\u30E9\u30D9\u30EB\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 +compiler.err.pattern.dominated=\u5148\u884C\u3059\u308Bcase\u30E9\u30D9\u30EB\u304C\u3001\u3053\u306Ecase\u30E9\u30D9\u30EB\u3088\u308A\u3082\u512A\u4F4D\u3067\u3059 + compiler.err.duplicate.default.label=default\u30E9\u30D9\u30EB\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 +compiler.err.duplicate.total.pattern=\u5408\u8A08\u30D1\u30BF\u30FC\u30F3\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 + +compiler.err.total.pattern.and.default=switch\u306B\u5408\u8A08\u30D1\u30BF\u30FC\u30F3\u3068default\u30E9\u30D9\u30EB\u306E\u4E21\u65B9\u304C\u3042\u308A\u307E\u3059 + +# 0: type, 1: type +compiler.err.constant.label.not.compatible=\u30BF\u30A4\u30D7{0}\u306E\u5B9A\u6570\u30E9\u30D9\u30EB\u304Cswitch\u30BB\u30EC\u30AF\u30BF\u30FB\u30BF\u30A4\u30D7{1}\u3068\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093 + +compiler.err.flows.through.to.pattern=\u30D1\u30BF\u30FC\u30F3\u306B\u5BFE\u3057\u3066\u4E0D\u6B63\u306Afall-through + +compiler.err.flows.through.from.pattern=\u30D1\u30BF\u30FC\u30F3\u304B\u3089\u306E\u4E0D\u6B63\u306Afall-through + compiler.err.else.without.if=''else''\u3078\u306E''if''\u304C\u3042\u308A\u307E\u305B\u3093 compiler.err.empty.char.lit=\u7A7A\u306E\u6587\u5B57\u30EA\u30C6\u30E9\u30EB\u3067\u3059 @@ -379,13 +394,13 @@ compiler.err.encl.class.required={0}\u3092\u542B\u3080\u56F2\u3046\u30A4\u30F3\u compiler.err.enum.annotation.must.be.enum.constant=\u5217\u6319\u578B\u6CE8\u91C8\u5024\u306F\u3001\u5217\u6319\u578B\u5B9A\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 -compiler.err.enum.cant.be.instantiated=\u5217\u6319\u578B\u306F\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u5316\u3067\u304D\u307E\u305B\u3093 +compiler.err.enum.cant.be.instantiated=\u5217\u6319\u30AF\u30E9\u30B9\u306F\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u5316\u3067\u304D\u307E\u305B\u3093 compiler.err.enum.label.must.be.unqualified.enum=\u5217\u6319\u578B\u306Eswitch case\u30E9\u30D9\u30EB\u306F\u5217\u6319\u578B\u5B9A\u6570\u306E\u975E\u4FEE\u98FE\u540D\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 compiler.err.enum.no.subclassing=\u30AF\u30E9\u30B9\u306F\u76F4\u63A5java.lang.Enum\u3092\u62E1\u5F35\u3067\u304D\u307E\u305B\u3093 -compiler.err.enum.types.not.extensible=\u5217\u6319\u578B\u306F\u62E1\u5F35\u53EF\u80FD\u3067\u306F\u3042\u308A\u307E\u305B\u3093 +compiler.err.enum.types.not.extensible=\u5217\u6319\u30AF\u30E9\u30B9\u306F\u62E1\u5F35\u53EF\u80FD\u3067\u306F\u3042\u308A\u307E\u305B\u3093 compiler.err.enum.no.finalize=\u5217\u6319\u578B\u306Ffinalize\u30E1\u30BD\u30C3\u30C9\u3092\u6301\u3064\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 @@ -495,21 +510,21 @@ compiler.err.incomparable.types=\u578B{0}\u3068{1}\u306F\u6BD4\u8F03\u3067\u304D # 0: string compiler.err.int.number.too.large=\u6574\u6570\u304C\u5927\u304D\u3059\u304E\u307E\u3059\u3002 -compiler.err.intf.annotation.members.cant.have.params=\u6CE8\u91C8\u578B\u5BA3\u8A00\u5185\u306E\u8981\u7D20\u304C\u4EEE\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u5BA3\u8A00\u3067\u304D\u307E\u305B\u3093 +compiler.err.intf.annotation.members.cant.have.params=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u5BA3\u8A00\u5185\u306E\u8981\u7D20\u304C\u4EEE\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u5BA3\u8A00\u3067\u304D\u307E\u305B\u3093 # 0: symbol -compiler.err.intf.annotation.cant.have.type.params=\u6CE8\u91C8\u578B{0}\u306F\u6C4E\u7528\u306B\u3067\u304D\u307E\u305B\u3093 +compiler.err.intf.annotation.cant.have.type.params=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9{0}\u306F\u6C4E\u7528\u306B\u3067\u304D\u307E\u305B\u3093 -compiler.err.intf.annotation.members.cant.have.type.params=\u6CE8\u91C8\u578B\u5BA3\u8A00\u5185\u306E\u8981\u7D20\u306F\u6C4E\u7528\u30E1\u30BD\u30C3\u30C9\u306B\u3067\u304D\u307E\u305B\u3093 +compiler.err.intf.annotation.members.cant.have.type.params=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u5BA3\u8A00\u5185\u306E\u8981\u7D20\u306F\u6C4E\u7528\u30E1\u30BD\u30C3\u30C9\u306B\u3067\u304D\u307E\u305B\u3093 # 0: symbol, 1: type -compiler.err.intf.annotation.member.clash=\u6CE8\u91C8\u578B{1}\u3067\u30E1\u30BD\u30C3\u30C9{0}\u3068\u540C\u3058\u540D\u524D\u306E\u8981\u7D20\u304C\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059 +compiler.err.intf.annotation.member.clash=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9{1}\u3067\u30E1\u30BD\u30C3\u30C9{0}\u3068\u540C\u3058\u540D\u524D\u306E\u8981\u7D20\u304C\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059 compiler.err.intf.expected.here=\u3053\u3053\u306B\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u304C\u5FC5\u8981\u3067\u3059 compiler.err.intf.meth.cant.have.body=\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u62BD\u8C61\u30E1\u30BD\u30C3\u30C9\u304C\u672C\u4F53\u3092\u6301\u3064\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 -compiler.err.invalid.annotation.member.type=\u6CE8\u91C8\u578B\u8981\u7D20\u306E\u578B\u304C\u7121\u52B9\u3067\u3059 +compiler.err.invalid.annotation.member.type=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u8981\u7D20\u306E\u578B\u304C\u7121\u52B9\u3067\u3059 compiler.err.invalid.binary.number=2\u9032\u6570\u5B57\u306F\u5C11\u306A\u304F\u3068\u30821\u6841\u306E2\u9032\u6570\u3092\u542B\u3080\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 @@ -535,7 +550,7 @@ compiler.err.label.already.in.use=\u30E9\u30D9\u30EB{0}\u306F\u3059\u3067\u306B\ # 0: symbol compiler.err.local.var.accessed.from.icls.needs.final=\u30ED\u30FC\u30AB\u30EB\u5909\u6570{0}\u306F\u5185\u90E8\u30AF\u30E9\u30B9\u304B\u3089\u30A2\u30AF\u30BB\u30B9\u3055\u308C\u307E\u3059\u3002final\u3067\u5BA3\u8A00\u3055\u308C\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 -compiler.err.local.enum=\u5217\u6319\u578B\u306F\u30ED\u30FC\u30AB\u30EB\u306B\u3067\u304D\u307E\u305B\u3093 +compiler.err.local.enum=\u5217\u6319\u30AF\u30E9\u30B9\u306F\u30ED\u30FC\u30AB\u30EB\u306B\u3067\u304D\u307E\u305B\u3093 compiler.err.cannot.create.array.with.type.arguments=\u578B\u5F15\u6570\u3092\u6301\u3064\u914D\u5217\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093 @@ -649,7 +664,7 @@ compiler.err.no.intf.expected.here=\u3053\u3053\u306B\u30A4\u30F3\u30BF\u30D5\u3 compiler.err.no.match.entry={0}\u306F{1}\u306E\u30A8\u30F3\u30C8\u30EA\u306B\u9069\u5408\u3057\u307E\u305B\u3093\u3002{2}\u304C\u5FC5\u8981\u3067\u3059 # 0: type -compiler.err.not.annotation.type={0}\u306F\u6CE8\u91C8\u578B\u3067\u306F\u3042\u308A\u307E\u305B\u3093 +compiler.err.not.annotation.type={0}\u306F\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 # 0: symbol, 1: symbol, 2: message segment compiler.err.not.def.access.package.cant.access={0} \u306F\u8868\u793A\u4E0D\u53EF\u3067\u3059\n({2}) @@ -836,6 +851,8 @@ compiler.err.static.imp.only.classes.and.interfaces=static import\u306F\u30AF\u3 compiler.err.string.const.req=\u5B9A\u6570\u306E\u6587\u5B57\u5217\u5F0F\u304C\u5FC5\u8981\u3067\u3059 +compiler.err.pattern.expected=\u30BF\u30A4\u30D7\u306E\u30D1\u30BF\u30FC\u30F3\u304C\u5FC5\u8981\u3067\u3059 + # 0: symbol, 1: fragment compiler.err.cannot.generate.class=\u30AF\u30E9\u30B9{0}\u306E\u751F\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\n({1}) @@ -966,6 +983,8 @@ compiler.err.unreachable.stmt=\u3053\u306E\u6587\u306B\u5236\u5FA1\u304C\u79FB\u compiler.err.not.exhaustive=switch\u5F0F\u304C\u3059\u3079\u3066\u306E\u53EF\u80FD\u306A\u5165\u529B\u5024\u3092\u30AB\u30D0\u30FC\u3057\u3066\u3044\u307E\u305B\u3093 +compiler.err.not.exhaustive.statement=switch\u6587\u304C\u3059\u3079\u3066\u306E\u53EF\u80FD\u306A\u5165\u529B\u5024\u3092\u30AB\u30D0\u30FC\u3057\u3066\u3044\u307E\u305B\u3093 + compiler.err.initializer.must.be.able.to.complete.normally=\u521D\u671F\u5316\u5B50\u306F\u6B63\u5E38\u306B\u5B8C\u4E86\u3067\u304D\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 compiler.err.initializer.not.allowed=\u30A4\u30CB\u30B7\u30E3\u30E9\u30A4\u30B6\u306Finterfaces\u3067\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 @@ -1006,7 +1025,7 @@ compiler.misc.varargs.trustme.on.reifiable.varargs=\u53EF\u5909\u5F15\u6570\u898 compiler.err.instanceof.reifiable.not.safe={0}\u3092{1}\u306B\u5B89\u5168\u306B\u30AD\u30E3\u30B9\u30C8\u3067\u304D\u307E\u305B\u3093 # 0: type, 1: type -compiler.err.instanceof.pattern.no.subtype=\u30D1\u30BF\u30FC\u30F3\u30FB\u30BF\u30A4\u30D7{0}\u306F\u5F0F\u30BF\u30A4\u30D7{1}\u306E\u30B5\u30D6\u30BF\u30A4\u30D7\u3067\u3059 +compiler.err.instanceof.pattern.no.subtype=\u5F0F\u30BF\u30A4\u30D7{0}\u306F\u30D1\u30BF\u30FC\u30F3\u30FB\u30BF\u30A4\u30D7{1}\u306E\u30B5\u30D6\u30BF\u30A4\u30D7\u3067\u3059 # 0: symbol compiler.misc.varargs.trustme.on.non.varargs.meth=\u30E1\u30BD\u30C3\u30C9{0}\u306F\u53EF\u5909\u5F15\u6570\u30E1\u30BD\u30C3\u30C9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002 @@ -1073,12 +1092,12 @@ compiler.err.locn.invalid.arg.for.xpatch=--patch-module\u30AA\u30D7\u30B7\u30E7\ compiler.err.file.sb.on.source.or.patch.path.for.module=\u30D5\u30A1\u30A4\u30EB\u306F\u3001\u30BD\u30FC\u30B9\u30FB\u30D1\u30B9\u3001\u307E\u305F\u306F\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30D1\u30C3\u30C1\u30FB\u30D1\u30B9\u306B\u5B58\u5728\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +compiler.err.no.java.lang=\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u30FB\u30AF\u30E9\u30B9\u3067\u30D1\u30C3\u30B1\u30FC\u30B8java.lang\u3092\u691C\u51FA\u3067\u304D\u307E\u305B\u3093 + ##### # Fatal Errors -compiler.misc.fatal.err.no.java.lang=\u81F4\u547D\u7684\u30A8\u30E9\u30FC: \u30AF\u30E9\u30B9\u30D1\u30B9\u307E\u305F\u306F\u30D6\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9\u30D1\u30B9\u3067\u30D1\u30C3\u30B1\u30FC\u30B8java.lang\u3092\u691C\u51FA\u3067\u304D\u307E\u305B\u3093 - # 0: name compiler.misc.fatal.err.cant.locate.meth=\u81F4\u547D\u7684\u30A8\u30E9\u30FC: \u30E1\u30BD\u30C3\u30C9{0}\u3092\u691C\u51FA\u3067\u304D\u307E\u305B\u3093 @@ -1168,19 +1187,21 @@ compiler.note.unchecked.filename.additional={0}\u306B\u672A\u30C1\u30A7\u30C3\u3 compiler.note.unchecked.plural.additional=\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u64CD\u4F5C\u306E\u3046\u3061\u3001\u672A\u30C1\u30A7\u30C3\u30AF\u307E\u305F\u306F\u5B89\u5168\u3067\u306F\u306A\u3044\u3082\u306E\u304C\u3055\u3089\u306B\u3042\u308A\u307E\u3059\u3002 -# 0: file name -compiler.note.preview.filename={0}\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u8A00\u8A9E\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 +# 0: file name, 1: source +compiler.note.preview.filename={0}\u306FJava SE {1}\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 -compiler.note.preview.plural=\u4E00\u90E8\u306E\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u8A00\u8A9E\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 +# 0: source +compiler.note.preview.plural=\u4E00\u90E8\u306E\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306FJava SE {0}\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 # The following string may appear after one of the above deprecation # messages. compiler.note.preview.recompile=\u8A73\u7D30\u306F\u3001-Xlint:preview\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3057\u3066\u518D\u30B3\u30F3\u30D1\u30A4\u30EB\u3057\u3066\u304F\u3060\u3055\u3044\u3002 -# 0: file name -compiler.note.preview.filename.additional={0}\u306F\u8FFD\u52A0\u3067\u30D7\u30EC\u30D3\u30E5\u30FC\u8A00\u8A9E\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 +# 0: file name, 1: source +compiler.note.preview.filename.additional={0}\u306BJava SE {1}\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u306E\u8FFD\u52A0\u4F7F\u7528\u304C\u3042\u308A\u307E\u3059\u3002 -compiler.note.preview.plural.additional=\u4E00\u90E8\u306E\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306F\u8FFD\u52A0\u3067\u30D7\u30EC\u30D3\u30E5\u30FC\u8A00\u8A9E\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 +# 0: source +compiler.note.preview.plural.additional=\u4E00\u90E8\u306E\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306FJava SE {0}\u306E\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u3092\u8FFD\u52A0\u4F7F\u7528\u3057\u307E\u3059\u3002 # Notes related to annotation processing @@ -1269,6 +1290,8 @@ compiler.warn.dir.path.element.not.directory=\u4E0D\u6B63\u306A\u30D1\u30B9\u898 # 0: symbol, 1: symbol, 2: symbol compiler.warn.missing-explicit-ctor=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3055\u308C\u305F\u30D1\u30C3\u30B1\u30FC\u30B8{1}\u306E\u30AF\u30E9\u30B9{0}\u306F\u660E\u793A\u7684\u306A\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u3092\u5BA3\u8A00\u3057\u306A\u3044\u305F\u3081\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u3092\u30E2\u30B8\u30E5\u30FC\u30EB{2}\u306E\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u306B\u516C\u958B\u3057\u307E\u3059 +compiler.warn.strictfp=\u30EA\u30EA\u30FC\u30B917\u4EE5\u964D\u3001\u3059\u3079\u3066\u306E\u6D6E\u52D5\u5C0F\u6570\u70B9\u5F0F\u306F\u53B3\u5BC6\u306B\u8A55\u4FA1\u3055\u308C\u3001''strictfp''\u306F\u5FC5\u8981\u3042\u308A\u307E\u305B\u3093 + compiler.warn.finally.cannot.complete=finally\u7BC0\u304C\u6B63\u5E38\u306B\u5B8C\u4E86\u3067\u304D\u307E\u305B\u3093 # 0: name @@ -1284,10 +1307,13 @@ compiler.warn.has.been.deprecated={1}\u306E{0}\u306F\u63A8\u5968\u3055\u308C\u30 compiler.warn.has.been.deprecated.for.removal={1}\u306E{0}\u306F\u63A8\u5968\u3055\u308C\u3066\u304A\u3089\u305A\u3001\u524A\u9664\u7528\u306B\u30DE\u30FC\u30AF\u3055\u308C\u3066\u3044\u307E\u3059 # 0: symbol -compiler.warn.is.preview={0}\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u306E\u4E00\u90E8\u3067\u3042\u308BAPI\u3067\u3059 +compiler.warn.is.preview={0}\u306F\u30D7\u30EC\u30D3\u30E5\u30FCAPI\u3067\u3042\u308A\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002 # 0: symbol -compiler.err.is.preview={0}\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u306E\u4E00\u90E8\u3067\u3042\u308BAPI\u3067\u3059 +compiler.err.is.preview={0}\u306F\u30D7\u30EC\u30D3\u30E5\u30FCAPI\u3067\u3042\u308A\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002\n(\u30D7\u30EC\u30D3\u30E5\u30FCAPI\u3092\u6709\u52B9\u306B\u3059\u308B\u306B\u306F--enable-preview\u3092\u4F7F\u7528\u3057\u307E\u3059) + +# 0: symbol +compiler.warn.is.preview.reflective={0}\u306F\u30EA\u30D5\u30EC\u30AF\u30C6\u30A3\u30D6\u30FB\u30D7\u30EC\u30D3\u30E5\u30FCAPI\u3067\u3042\u308A\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002 # 0: symbol compiler.warn.has.been.deprecated.module=\u30E2\u30B8\u30E5\u30FC\u30EB{0}\u306F\u63A8\u5968\u3055\u308C\u307E\u305B\u3093 @@ -1303,6 +1329,11 @@ compiler.warn.illegal.char.for.encoding=\u3053\u306E\u6587\u5B57\u306F\u3001\u30 # 0: symbol compiler.warn.improper.SVUID=serialVersionUID\u306F\u3001\u30AF\u30E9\u30B9{0}\u306Bstatic final\u3092\u5BA3\u8A00\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +compiler.warn.improper.SPF=serialPersistentFields\u3092\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001private static final\u3068\u3057\u3066\u5BA3\u8A00\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 + +compiler.warn.SPF.null.init=null\u306B\u521D\u671F\u5316\u3059\u308B\u3068serialPersistentFields\u306F\u7121\u52B9\u306B\u306A\u308A\u307E\u3059\u3002\n\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u306A\u3044\u3053\u3068\u3092\u793A\u3059\u306B\u306F\u3001\u7A7A\u306E\u914D\u5217\u306B\u521D\u671F\u5316\u3057\u307E\u3059 + + # 0: type, 1: type compiler.warn.inexact.non-varargs.call=\u6700\u7D42\u30D1\u30E9\u30E1\u30FC\u30BF\u306E\u4E0D\u6B63\u78BA\u306A\u5F15\u6570\u578B\u3092\u6301\u3063\u305F\u53EF\u5909\u5F15\u6570\u30E1\u30BD\u30C3\u30C9\u306E\u975E\u53EF\u5909\u5F15\u6570\u547C\u51FA\u3057\u3002\n\u53EF\u5909\u5F15\u6570\u547C\u51FA\u3057\u306B\u95A2\u3057\u3066\u306F{0}\u306B\u30AD\u30E3\u30B9\u30C8\u3057\u307E\u3059\u3002\n\u975E\u53EF\u5909\u5F15\u6570\u547C\u51FA\u3057\u306B\u95A2\u3057\u3066\u306F{1}\u306B\u30AD\u30E3\u30B9\u30C8\u3057\u3066\u3053\u306E\u8B66\u544A\u3092\u51FA\u3055\u306A\u3044\u3088\u3046\u306B\u3057\u307E\u3059 @@ -1315,9 +1346,67 @@ compiler.warn.unreachable.catch.1=catch\u53E5\u306B\u79FB\u3059\u3053\u3068\u304 # 0: symbol compiler.warn.long.SVUID=serialVersionUID\u306F\u3001\u30AF\u30E9\u30B9{0}\u306Elong\u578B\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +compiler.warn.OSF.array.SPF=serialPersistentFields\u3092\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30BF\u30A4\u30D7\u3092java.io.ObjectStreamField[]\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 + # 0: symbol compiler.warn.missing.SVUID=\u76F4\u5217\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9{0}\u306B\u306F\u3001serialVersionUID\u304C\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u305B\u3093 +# 0: name +compiler.warn.serializable.missing.access.no.arg.ctor=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u4E0D\u53EF\u306E\u30B9\u30FC\u30D1\u30FC\u30AF\u30E9\u30B9{0}\u3067\u5F15\u6570\u306A\u3057\u306E\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093 + +# 0: name +compiler.warn.serial.method.not.private=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306Fprivate\u3068\u3057\u3066\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u305B\u3093 + +# 0: name +compiler.warn.serial.concrete.instance.method=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u3092\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001concrete\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u30FB\u30E1\u30BD\u30C3\u30C9\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002abstract\u3067\u3082static\u3067\u3082\u3042\u308A\u307E\u305B\u3093 + +# 0: name +compiler.warn.serial.method.static=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u304Cstatic\u3068\u3057\u3066\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u304B\u308F\u308A\u306B\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u30FB\u30E1\u30BD\u30C3\u30C9\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 + +# 0: name +compiler.warn.serial.method.no.args=\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306B\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044 + +# 0: name, 1: number +compiler.warn.serial.method.one.arg=\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306B\u3001{1}\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u306F\u306A\u304F\u3001\u30D1\u30E9\u30E1\u30FC\u30BF\u30921\u3064\u306E\u307F\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.parameter.type=\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306E1\u3064\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3001\u578B{2}\u3067\u306F\u306A\u304F\u3001\u578B{1}\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.unexpected.return.type=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306F\u3001\u5FC5\u8981\u306A\u578B{2}\u3067\u306F\u306A\u304F\u3001{1}\u306E\u623B\u308A\u578B\u3067\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u3088\u3046\u306B\u3001\u30E1\u30BD\u30C3\u30C9\u306F\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u304C\u7121\u52B9\u306B\u306A\u308A\u307E\u3059 + +# 0: name, 1: type +compiler.warn.serial.method.unexpected.exception=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306F\u4E88\u671F\u3057\u306A\u3044\u578B{1}\u3092\u30B9\u30ED\u30FC\u3059\u308B\u3088\u3046\u306B\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059 + +compiler.warn.ineffectual.serial.field.interface=serialPersistentFields\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +# 0: string +compiler.warn.ineffectual.serial.field.enum=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30D5\u30A3\u30FC\u30EB\u30C9{0}\u306F\u5217\u6319\u30AF\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +# 0: string +compiler.warn.ineffectual.serial.method.enum=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306F\u5217\u6319\u30AF\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +compiler.warn.ineffectual.serial.field.record=serialPersistentFields\u306F\u30EC\u30B3\u30FC\u30C9\u30FB\u30AF\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +# 0: string +compiler.warn.ineffectual.serial.method.record=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306F\u30EC\u30B3\u30FC\u30C9\u30FB\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +# 0: name +compiler.warn.ineffectual.serial.method.externalizable=\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9{0}\u306F\u5916\u90E8\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields\u306F\u5916\u90E8\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +compiler.warn.externalizable.missing.public.no.arg.ctor=\u5916\u90E8\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u306B\u306F\u5F15\u6570\u306A\u3057\u3067\u30D1\u30D6\u30EA\u30C3\u30AF\u306E\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u304C\u5FC5\u8981\u3067\u3059 + +compiler.warn.non.serializable.instance.field=\u76F4\u5217\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u306E\u5E38\u99D0\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u30FB\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u76F4\u5217\u4E0D\u53EF\u30BF\u30A4\u30D7\u3067\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059 + +# 0: type +compiler.warn.non.serializable.instance.field.array=\u76F4\u5217\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u306E\u5E38\u99D0\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u30FB\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u3001\u76F4\u5217\u4E0D\u53EF\u306E\u30D9\u30FC\u30B9\u30FB\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u30FB\u30BF\u30A4\u30D7{0}\u3092\u6301\u3064\u914D\u5217\u3067\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059 + +compiler.warn.non.private.method.weaker.access=\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067private\u3068\u3057\u3066\u5BA3\u8A00\u3055\u308C\u305F\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u30E1\u30BD\u30C3\u30C9\u306B\u3088\u3063\u3066\u3001\n\u305D\u306E\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3092\u5B9F\u88C5\u3059\u308B\u30AF\u30E9\u30B9\u304C\u30E1\u30BD\u30C3\u30C9\u3092private\u3068\u3057\u3066\u5BA3\u8A00\u3067\u304D\u306A\u304F\u306A\u308A\u307E\u3059 + +compiler.warn.default.ineffective=\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u95A2\u9023\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30E1\u30BD\u30C3\u30C9\u306F\u3001\u30AF\u30E9\u30B9\u3092\u5B9F\u88C5\u3059\u308B\u305F\u3081\u306E\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3067\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093 + # 0: symbol, 1: symbol, 2: symbol, 3: symbol compiler.warn.potentially.ambiguous.overload={1}\u5185\u306E{0}\u306F{3}\u5185\u306E{2}\u3068\u77DB\u76FE\u3059\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059 @@ -1404,7 +1493,7 @@ compiler.warn.proc.suspicious.class.name=\u540D\u524D\u304C{1}\u3067\u7D42\u308F compiler.warn.proc.file.create.last.round=\u6700\u5F8C\u306B\u4F5C\u6210\u3055\u308C\u305F\u30BF\u30A4\u30D7''{0}''\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u6CE8\u91C8\u51E6\u7406\u306B\u6E21\u3055\u308C\u307E\u305B\u3093\u3002 # 0: string, 1: string -compiler.warn.proc.malformed.supported.string=\u30D7\u30ED\u30BB\u30C3\u30B5''{1}''\u304C\u8FD4\u3057\u305F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u308B\u6CE8\u91C8\u578B\u306E\u6587\u5B57\u5217''{0}''\u304C\u4E0D\u6B63\u3067\u3059 +compiler.warn.proc.malformed.supported.string=\u30D7\u30ED\u30BB\u30C3\u30B5''{1}''\u304C\u8FD4\u3057\u305F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u308B\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u6587\u5B57\u5217''{0}''\u304C\u4E0D\u6B63\u3067\u3059 # 0: set of string compiler.warn.proc.annotations.without.processors=\u3053\u308C\u3089\u306E\u6CE8\u91C8\u3092\u8981\u6C42\u3059\u308B\u30D7\u30ED\u30BB\u30C3\u30B5\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F: {0} @@ -1416,10 +1505,10 @@ compiler.warn.proc.processor.incompatible.source.version=\u6CE8\u91C8\u30D7\u30E compiler.warn.proc.duplicate.option.name=\u91CD\u8907\u3059\u308B\u30B5\u30DD\u30FC\u30C8\u5BFE\u8C61\u30AA\u30D7\u30B7\u30E7\u30F3''{0}''\u304C\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5''{1}''\u306B\u3088\u3063\u3066\u8FD4\u3055\u308C\u307E\u3057\u305F # 0: string, 1: string -compiler.warn.proc.duplicate.supported.annotation=\u91CD\u8907\u3059\u308B\u30B5\u30DD\u30FC\u30C8\u5BFE\u8C61\u6CE8\u91C8\u578B''{0}''\u304C\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5''{1}''\u306B\u3088\u3063\u3066\u8FD4\u3055\u308C\u307E\u3057\u305F +compiler.warn.proc.duplicate.supported.annotation=\u91CD\u8907\u3059\u308B\u30B5\u30DD\u30FC\u30C8\u5BFE\u8C61\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9''{0}''\u304C\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5''{1}''\u306B\u3088\u3063\u3066\u8FD4\u3055\u308C\u307E\u3057\u305F # 0: string -compiler.warn.proc.redundant.types.with.wildcard=\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5''{0}''\u306F''*''\u3068\u4ED6\u306E\u6CE8\u91C8\u578B\u3092\u91CD\u8907\u3057\u3066\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059 +compiler.warn.proc.redundant.types.with.wildcard=\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5''{0}''\u306F''*''\u3068\u4ED6\u306E\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3092\u91CD\u8907\u3057\u3066\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059 compiler.warn.proc.proc-only.requested.no.procs=\u30B3\u30F3\u30D1\u30A4\u30EB\u306A\u3057\u306E\u6CE8\u91C8\u51E6\u7406\u304C\u30EA\u30AF\u30A8\u30B9\u30C8\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u30D7\u30ED\u30BB\u30C3\u30B5\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 @@ -1475,6 +1564,8 @@ compiler.warn.deprecated.annotation.has.no.effect=@Deprecated\u6CE8\u91C8\u306F\ # 0: string compiler.warn.invalid.path=\u30D5\u30A1\u30A4\u30EB\u540D\u304C\u7121\u52B9\u3067\u3059: {0} +compiler.warn.doclint.not.available=\u4F7F\u7528\u53EF\u80FD\u306Adoclint\u306E\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0\u306F\u3042\u308A\u307E\u305B\u3093 + # 0: string compiler.err.invalid.path=\u30D5\u30A1\u30A4\u30EB\u540D\u304C\u7121\u52B9\u3067\u3059: {0} @@ -1577,8 +1668,6 @@ compiler.err.enum.constant.expected=\u3053\u3053\u306B\u5217\u6319\u578B\u5B9A\u compiler.err.enum.constant.not.expected=\u3053\u3053\u306B\u5217\u6319\u578B\u5B9A\u6570\u306F\u5FC5\u8981\u3042\u308A\u307E\u305B\u3093 ## The following are related in form, but do not easily fit the above paradigm. -compiler.err.expected.module=''\u30E2\u30B8\u30E5\u30FC\u30EB''\u304C\u5FC5\u8981\u3067\u3059 - compiler.err.expected.module.or.open=''\u30E2\u30B8\u30E5\u30FC\u30EB''\u307E\u305F\u306F''\u30AA\u30FC\u30D7\u30F3''\u304C\u5FC5\u8981\u3067\u3059 compiler.err.dot.class.expected=''.class''\u304C\u3042\u308A\u307E\u305B\u3093 @@ -2103,6 +2192,10 @@ compiler.misc.feature.records=\u30EC\u30B3\u30FC\u30C9 compiler.misc.feature.sealed.classes=\u30B7\u30FC\u30EB\u30FB\u30AF\u30E9\u30B9 +compiler.misc.feature.case.null=switch case\u306Enull + +compiler.misc.feature.pattern.switch=switch\u6587\u306E\u30D1\u30BF\u30FC\u30F3 + compiler.warn.underscore.as.identifier=\u30EA\u30EA\u30FC\u30B99\u304B\u3089''_''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 compiler.err.underscore.as.identifier=\u30EA\u30EA\u30FC\u30B99\u304B\u3089''_''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 @@ -2174,6 +2267,28 @@ compiler.note.deferred.method.inst=\u30E1\u30BD\u30C3\u30C9{0}\u306E\u9045\u5EF6 # 0: symbol compiler.note.verbose.l2m.deduplicate=\u91CD\u8907\u9664\u5916\u30E9\u30E0\u30C0\u5B9F\u88C5\u30E1\u30BD\u30C3\u30C9{0} +######################################## +# Diagnostics for method reference search +# results used by Resolve (debug only) +######################################## + +# 0: fragment, 1: string, 2: number +compiler.note.method.ref.search.results.multi={1}\u306E{0}\u306E\u691C\u7D22\u7D50\u679C(\u6700\u3082\u53B3\u5BC6\u306A\u3082\u306E{2}\u500B)\n\u4F7F\u7528\u53EF\u80FD\u306A\u5019\u88DC: + +# 0: number, 1: fragment, 2: symbol +compiler.misc.applicable.method.found.2=\u4F7F\u7528\u53EF\u80FD\u30E1\u30BD\u30C3\u30C9\u304C#{0}\u500B\u898B\u3064\u304B\u308A\u307E\u3057\u305F: {1} {2} + +# 0: number, 1: fragment, 2: symbol, 3: message segment +compiler.misc.applicable.method.found.3=\u4F7F\u7528\u53EF\u80FD\u30E1\u30BD\u30C3\u30C9\u304C#{0}\u500B\u898B\u3064\u304B\u308A\u307E\u3057\u305F: {1} {2}\n({3}) + +compiler.misc.static=static + +compiler.misc.non.static=static\u3067\u306A\u3044 + +compiler.misc.bound=\u30D0\u30A4\u30F3\u30C9 + +compiler.misc.unbound=\u30D0\u30A4\u30F3\u30C9\u306A\u3057 + ######################################## # Diagnostics for where clause implementation # used by the RichDiagnosticFormatter. @@ -2260,7 +2375,7 @@ compiler.err.dc.no.tag.name='@'\u306E\u5F8C\u306B\u30BF\u30B0\u540D\u304C\u3042\ compiler.err.dc.gt.expected=''>''\u304C\u5FC5\u8981\u3067\u3059 -compiler.err.dc.ref.bad.parens=\u53C2\u7167\u306B'')''\u304C\u3042\u308A\u307E\u305B\u3093 +compiler.err.dc.ref.bad.parens=\u30AB\u30C3\u30B3\u306E\u5F8C\u306E\u4E88\u671F\u3057\u306A\u3044\u30C6\u30AD\u30B9\u30C8\u3067\u3059 compiler.err.dc.ref.syntax.error=\u53C2\u7167\u306B\u69CB\u6587\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059 @@ -2274,6 +2389,8 @@ compiler.err.dc.unterminated.signature=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u7D4 compiler.err.dc.unterminated.string=\u6587\u5B57\u5217\u304C\u7D42\u4E86\u3057\u3066\u3044\u307E\u305B\u3093 +compiler.err.dc.ref.annotations.not.allowed=\u6CE8\u91C8\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 + ### # errors related to modules @@ -2450,8 +2567,6 @@ compiler.err.illegal.argument.for.option={0}\u306E\u5F15\u6570\u304C\u4E0D\u6B63 compiler.err.match.binding.exists=\u65E2\u5B58\u306E\u4E00\u81F4\u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u3092\u518D\u5B9A\u7FA9\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 -compiler.err.switch.null.not.allowed=case\u306Enull\u30E9\u30D9\u30EB\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093 - compiler.err.switch.case.unexpected.statement=case\u306E\u4E88\u671F\u3057\u306A\u3044\u6587\u3067\u3059\u3002\u4E88\u671F\u3055\u308C\u308B\u306E\u306F\u3001\u5F0F\u3001\u30D6\u30ED\u30C3\u30AF\u307E\u305F\u306Fthrow\u6587\u3067\u3059 compiler.err.switch.mixing.case.types=switch\u3067case\u306E\u7570\u306A\u308B\u7A2E\u985E\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059 @@ -2664,5 +2779,7 @@ compiler.err.preview.not.latest=--enable-preview\u304C\u6307\u5B9A\u3055\u308C\u compiler.err.preview.without.source.or.release=--enable-preview\u306F-source\u307E\u305F\u306F--release\u3068\u3068\u3082\u306B\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 -compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\u5024\u30D9\u30FC\u30B9\u30FB\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3067\u540C\u671F\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F +# 0: kind name, 1: symbol +compiler.warn.declared.using.preview={0} {1}\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u3066\u5BA3\u8A00\u3055\u308C\u3066\u304A\u308A\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002 +compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\u5024\u30D9\u30FC\u30B9\u30FB\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3067\u540C\u671F\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 3c6e2ca34d3454069c2095c16fefee307b8861d1..01c92e9e0b3ad6d3315cd994d3c1699f4648b431 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -119,7 +119,7 @@ compiler.err.annotation.missing.default.value.1=\u5BF9\u4E8E\u5143\u7D20{1}, \u6 # 0: type compiler.err.annotation.not.valid.for.type=\u6CE8\u91CA\u5BF9\u4E8E\u7C7B\u578B{0}\u7684\u5143\u7D20\u65E0\u6548 -compiler.err.annotation.type.not.applicable=\u6CE8\u91CA\u7C7B\u578B\u4E0D\u9002\u7528\u4E8E\u8BE5\u7C7B\u578B\u7684\u58F0\u660E +compiler.err.annotation.type.not.applicable=\u6CE8\u91CA\u63A5\u53E3\u4E0D\u9002\u7528\u4E8E\u6B64\u7C7B\u578B\u7684\u58F0\u660E # 0: type compiler.err.annotation.type.not.applicable.to.type=\u6CE8\u91CA @{0} \u5728\u6B64\u7C7B\u578B\u4E0A\u4E0B\u6587\u4E2D\u4E0D\u9002\u7528 @@ -263,12 +263,14 @@ compiler.misc.lambda=lambda \u8868\u8FBE\u5F0F compiler.misc.inner.cls=\u5185\u90E8\u7C7B +compiler.misc.guard=\u536B\u58EB + # 0: type compiler.err.cant.deref=\u65E0\u6CD5\u53D6\u6D88\u5F15\u7528{0} compiler.err.cant.extend.intf.annotation=\u5BF9\u4E8E @interfaces, \u4E0D\u5141\u8BB8 ''extends'' -compiler.err.annotation.decl.not.allowed.here=\u6B64\u5904\u4E0D\u5141\u8BB8\u6CE8\u91CA\u7C7B\u578B\u58F0\u660E +compiler.err.annotation.decl.not.allowed.here=\u6B64\u5904\u4E0D\u5141\u8BB8\u6CE8\u91CA\u63A5\u53E3\u58F0\u660E # 0: symbol compiler.err.cant.inherit.from.final=\u65E0\u6CD5\u4ECE\u6700\u7EC8{0}\u8FDB\u884C\u7EE7\u627F @@ -307,7 +309,7 @@ compiler.err.no.superclass={0}\u4E0D\u5177\u6709\u8D85\u7C7B\u3002 # 0: symbol, 1: type, 2: symbol, 3: type, 4: type compiler.err.concrete.inheritance.conflict={1}\u4E2D\u7684\u65B9\u6CD5{0}\u548C{3}\u4E2D\u7684\u65B9\u6CD5{2}\u662F\u4F7F\u7528\u76F8\u540C\u7684\u7B7E\u540D\u7EE7\u627F\u7684 -compiler.err.default.allowed.in.intf.annotation.member=\u6CE8\u91CA\u7C7B\u578B\u58F0\u660E\u4E2D\u4EC5\u5141\u8BB8\u9ED8\u8BA4\u503C +compiler.err.default.allowed.in.intf.annotation.member=\u6CE8\u91CA\u63A5\u53E3\u58F0\u660E\u4E2D\u4EC5\u5141\u8BB8\u9ED8\u8BA4\u503C # 0: symbol compiler.err.doesnt.exist=\u7A0B\u5E8F\u5305{0}\u4E0D\u5B58\u5728 @@ -319,7 +321,7 @@ compiler.err.duplicate.annotation.invalid.repeated=\u6CE8\u91CA{0}\u4E0D\u662F\u compiler.err.duplicate.annotation.member.value=\u6CE8\u91CA@{1}\u4E2D\u7684\u5143\u7D20 ''{0}'' \u91CD\u590D\u3002 # 0: type -compiler.err.duplicate.annotation.missing.container={0} \u4E0D\u662F\u53EF\u91CD\u590D\u7684\u6CE8\u91CA\u7C7B\u578B +compiler.err.duplicate.annotation.missing.container={0} \u4E0D\u662F\u53EF\u91CD\u590D\u7684\u6CE8\u91CA\u63A5\u53E3 # 0: symbol compiler.err.invalid.repeatable.annotation=\u6CE8\u91CA\u91CD\u590D: \u4F7F\u7528\u65E0\u6548\u7684 @Repeatable \u6CE8\u91CA\u5BF9{0}\u8FDB\u884C\u4E86\u6CE8\u91CA @@ -334,22 +336,22 @@ compiler.err.invalid.repeatable.annotation.multiple.values={0}\u4E0D\u662F\u6709 compiler.err.invalid.repeatable.annotation.invalid.value={0}\u4E0D\u662F\u6709\u6548\u7684 @Repeatable: \u503C\u5143\u7D20\u65E0\u6548 # 0: symbol or type, 1: type, 2: type -compiler.err.invalid.repeatable.annotation.value.return=\u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u5FC5\u987B\u58F0\u660E\u7C7B\u578B{2}\u7684\u540D\u4E3A ''value'' \u7684\u5143\u7D20 +compiler.err.invalid.repeatable.annotation.value.return=\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u5FC5\u987B\u58F0\u660E\u7C7B\u578B {2} \u7684\u540D\u4E3A ''value'' \u7684\u5143\u7D20 # 0: symbol or type, 1: symbol -compiler.err.invalid.repeatable.annotation.elem.nondefault=\u5BF9\u4E8E\u5143\u7D20 {1}, \u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u6CA1\u6709\u9ED8\u8BA4\u503C +compiler.err.invalid.repeatable.annotation.elem.nondefault=\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u6CA1\u6709\u5143\u7D20 {1} \u7684\u9ED8\u8BA4\u503C # 0: symbol, 1: string, 2: symbol, 3: string -compiler.err.invalid.repeatable.annotation.retention=\u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u7684\u4FDD\u7559\u671F\u77ED\u4E8E\u53EF\u91CD\u590D\u6CE8\u91CA\u7C7B\u578B ({2}) \u7684\u4FDD\u7559\u671F +compiler.err.invalid.repeatable.annotation.retention=\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u7684\u4FDD\u7559\u671F\u77ED\u4E8E\u53EF\u91CD\u590D\u6CE8\u91CA\u63A5\u53E3 ({2}) \u7684\u4FDD\u7559\u671F # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.not.documented=\u53EF\u91CD\u590D\u6CE8\u91CA\u7C7B\u578B ({1}) \u662F @Documented, \u800C\u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u5219\u4E0D\u662F +compiler.err.invalid.repeatable.annotation.not.documented=\u53EF\u91CD\u590D\u6CE8\u91CA\u63A5\u53E3 ({1}) \u662F @Documented\uFF0C\u800C\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u5219\u4E0D\u662F # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.not.inherited=\u53EF\u91CD\u590D\u6CE8\u91CA\u7C7B\u578B ({1}) \u662F @Inherited, \u800C\u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u5219\u4E0D\u662F +compiler.err.invalid.repeatable.annotation.not.inherited=\u53EF\u91CD\u590D\u6CE8\u91CA\u63A5\u53E3 ({1}) \u662F @Inherited\uFF0C\u800C\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u5219\u4E0D\u662F # 0: symbol, 1: symbol -compiler.err.invalid.repeatable.annotation.incompatible.target=\u5305\u542B\u6CE8\u91CA\u7C7B\u578B ({0}) \u9002\u7528\u7684\u76EE\u6807\u591A\u4E8E\u53EF\u91CD\u590D\u6CE8\u91CA\u7C7B\u578B ({1}) +compiler.err.invalid.repeatable.annotation.incompatible.target=\u5305\u542B\u6CE8\u91CA\u63A5\u53E3 ({0}) \u9002\u7528\u7684\u76EE\u6807\u591A\u4E8E\u53EF\u91CD\u590D\u6CE8\u91CA\u63A5\u53E3 ({1}) # 0: symbol compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\u5BB9\u5668 {0} \u4E0D\u5F97\u4E0E\u5176\u5305\u542B\u7684\u5143\u7D20\u540C\u65F6\u5B58\u5728 @@ -368,8 +370,21 @@ compiler.err.same.binary.name=\u7C7B\uFF1A{0} \u548C {1} \u5177\u6709\u76F8\u540 compiler.err.duplicate.case.label=case \u6807\u7B7E\u91CD\u590D +compiler.err.pattern.dominated=\u6B64 case \u6807\u7B7E\u7531\u524D\u4E00\u4E2A case \u6807\u7B7E\u652F\u914D + compiler.err.duplicate.default.label=default \u6807\u7B7E\u91CD\u590D +compiler.err.duplicate.total.pattern=\u603B\u8BA1\u6A21\u5F0F\u91CD\u590D + +compiler.err.total.pattern.and.default=switch \u6709\u4E00\u4E2A\u603B\u8BA1\u6A21\u5F0F\u548C\u4E00\u4E2A\u9ED8\u8BA4\u6807\u7B7E + +# 0: type, 1: type +compiler.err.constant.label.not.compatible={0} \u7C7B\u578B\u7684\u5E38\u91CF\u6807\u7B7E\u4E0E switch \u9009\u62E9\u5668\u7C7B\u578B {1} \u4E0D\u517C\u5BB9 + +compiler.err.flows.through.to.pattern=\u8D2F\u7A7F (fall-through) \u5230\u6A21\u5F0F\u975E\u6CD5 + +compiler.err.flows.through.from.pattern=\u4ECE\u6A21\u5F0F\u8D2F\u7A7F (fall-through) \u975E\u6CD5 + compiler.err.else.without.if=\u6709 ''if'', \u4F46\u662F\u6CA1\u6709 ''else'' compiler.err.empty.char.lit=\u7A7A\u5B57\u7B26\u6587\u5B57 @@ -379,13 +394,13 @@ compiler.err.encl.class.required=\u9700\u8981\u5305\u542B{0}\u7684\u5C01\u95ED\u compiler.err.enum.annotation.must.be.enum.constant=\u679A\u4E3E\u6CE8\u91CA\u503C\u5FC5\u987B\u662F\u679A\u4E3E\u5E38\u91CF -compiler.err.enum.cant.be.instantiated=\u65E0\u6CD5\u5B9E\u4F8B\u5316\u679A\u4E3E\u7C7B\u578B +compiler.err.enum.cant.be.instantiated=\u65E0\u6CD5\u5B9E\u4F8B\u5316\u679A\u4E3E\u7C7B compiler.err.enum.label.must.be.unqualified.enum=\u679A\u4E3E switch case \u6807\u7B7E\u5FC5\u987B\u4E3A\u679A\u4E3E\u5E38\u91CF\u7684\u975E\u9650\u5B9A\u540D\u79F0 compiler.err.enum.no.subclassing=\u7C7B\u65E0\u6CD5\u76F4\u63A5\u6269\u5C55 java.lang.Enum -compiler.err.enum.types.not.extensible=\u679A\u4E3E\u7C7B\u578B\u4E0D\u53EF\u7EE7\u627F +compiler.err.enum.types.not.extensible=\u679A\u4E3E\u7C7B\u4E0D\u53EF\u6269\u5C55 compiler.err.enum.no.finalize=\u679A\u4E3E\u4E0D\u80FD\u6709 finalize \u65B9\u6CD5 @@ -415,9 +430,9 @@ compiler.err.finally.without.try=\u6709 ''finally'', \u4F46\u662F\u6CA1\u6709 '' # 0: type, 1: message segment compiler.err.foreach.not.applicable.to.type=for-each \u4E0D\u9002\u7528\u4E8E\u8868\u8FBE\u5F0F\u7C7B\u578B\n\u8981\u6C42: {1}\n\u627E\u5230: {0} -compiler.err.fp.number.too.large=\u6D6E\u70B9\u6570\u8FC7\u5927 +compiler.err.fp.number.too.large=\u6D6E\u70B9\u6570\u592A\u5927 -compiler.err.fp.number.too.small=\u6D6E\u70B9\u6570\u8FC7\u5C0F +compiler.err.fp.number.too.small=\u6D6E\u70B9\u6570\u592A\u5C0F compiler.err.generic.array.creation=\u521B\u5EFA\u6CDB\u578B\u6570\u7EC4 @@ -495,21 +510,21 @@ compiler.err.incomparable.types=\u4E0D\u53EF\u6BD4\u8F83\u7684\u7C7B\u578B: {0}\ # 0: string compiler.err.int.number.too.large=\u6574\u6570\u592A\u5927 -compiler.err.intf.annotation.members.cant.have.params=\u6CE8\u91CA\u7C7B\u578B\u58F0\u660E\u4E2D\u7684\u5143\u7D20\u65E0\u6CD5\u58F0\u660E\u5F62\u53C2 +compiler.err.intf.annotation.members.cant.have.params=\u6CE8\u91CA\u63A5\u53E3\u58F0\u660E\u4E2D\u7684\u5143\u7D20\u65E0\u6CD5\u58F0\u660E\u5F62\u53C2 # 0: symbol -compiler.err.intf.annotation.cant.have.type.params=\u6CE8\u91CA\u7C7B\u578B {0} \u4E0D\u80FD\u4E3A\u6CDB\u578B +compiler.err.intf.annotation.cant.have.type.params=\u6CE8\u91CA\u63A5\u53E3 {0} \u4E0D\u80FD\u4E3A\u6CDB\u578B -compiler.err.intf.annotation.members.cant.have.type.params=\u6CE8\u91CA\u7C7B\u578B\u58F0\u660E\u4E2D\u7684\u5143\u7D20\u4E0D\u80FD\u4E3A\u6CDB\u578B\u65B9\u6CD5 +compiler.err.intf.annotation.members.cant.have.type.params=\u6CE8\u91CA\u63A5\u53E3\u58F0\u660E\u4E2D\u7684\u5143\u7D20\u4E0D\u80FD\u4E3A\u6CDB\u578B\u65B9\u6CD5 # 0: symbol, 1: type -compiler.err.intf.annotation.member.clash=\u6CE8\u91CA\u7C7B\u578B{1}\u58F0\u660E\u4E0E\u65B9\u6CD5 {0} \u540C\u540D\u7684\u5143\u7D20 +compiler.err.intf.annotation.member.clash=\u6CE8\u91CA\u63A5\u53E3 {1} \u58F0\u660E\u7684\u5143\u7D20\u4E0E\u65B9\u6CD5 {0} \u540C\u540D compiler.err.intf.expected.here=\u6B64\u5904\u9700\u8981\u63A5\u53E3 compiler.err.intf.meth.cant.have.body=\u63A5\u53E3\u62BD\u8C61\u65B9\u6CD5\u4E0D\u80FD\u5E26\u6709\u4E3B\u4F53 -compiler.err.invalid.annotation.member.type=\u6CE8\u91CA\u7C7B\u578B\u5143\u7D20\u7684\u7C7B\u578B\u65E0\u6548 +compiler.err.invalid.annotation.member.type=\u6CE8\u91CA\u63A5\u53E3\u5143\u7D20\u7684\u7C7B\u578B\u65E0\u6548 compiler.err.invalid.binary.number=\u4E8C\u8FDB\u5236\u6570\u5B57\u4E2D\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u4E2A\u4E8C\u8FDB\u5236\u6570 @@ -535,7 +550,7 @@ compiler.err.label.already.in.use=\u6807\u7B7E{0}\u5DF2\u4F7F\u7528 # 0: symbol compiler.err.local.var.accessed.from.icls.needs.final=\u4ECE\u5185\u90E8\u7C7B\u4E2D\u8BBF\u95EE\u672C\u5730\u53D8\u91CF{0}; \u9700\u8981\u88AB\u58F0\u660E\u4E3A\u6700\u7EC8\u7C7B\u578B -compiler.err.local.enum=\u679A\u4E3E\u7C7B\u578B\u4E0D\u80FD\u4E3A\u672C\u5730\u7C7B\u578B +compiler.err.local.enum=\u679A\u4E3E\u7C7B\u4E0D\u80FD\u4E3A\u672C\u5730\u7C7B compiler.err.cannot.create.array.with.type.arguments=\u65E0\u6CD5\u521B\u5EFA\u5177\u6709\u7C7B\u578B\u53D8\u91CF\u7684\u6570\u7EC4 @@ -649,7 +664,7 @@ compiler.err.no.intf.expected.here=\u6B64\u5904\u4E0D\u9700\u8981\u63A5\u53E3 compiler.err.no.match.entry={0}\u5728{1}\u7684\u6761\u76EE\u4E2D\u6CA1\u6709\u5339\u914D\u9879; \u9700\u8981{2} # 0: type -compiler.err.not.annotation.type={0}\u4E0D\u662F\u6CE8\u91CA\u7C7B\u578B +compiler.err.not.annotation.type={0} \u4E0D\u662F\u6CE8\u91CA\u63A5\u53E3 # 0: symbol, 1: symbol, 2: message segment compiler.err.not.def.access.package.cant.access={0} \u4E0D\u53EF\u89C1\n({2}) @@ -836,6 +851,8 @@ compiler.err.static.imp.only.classes.and.interfaces=\u4EC5\u4ECE\u7C7B\u548C\u63 compiler.err.string.const.req=\u9700\u8981\u5E38\u91CF\u5B57\u7B26\u4E32\u8868\u8FBE\u5F0F +compiler.err.pattern.expected=\u9700\u8981\u7C7B\u578B\u6A21\u5F0F + # 0: symbol, 1: fragment compiler.err.cannot.generate.class=\u751F\u6210\u7C7B {0} \u65F6\u51FA\u9519\n({1}) @@ -966,6 +983,8 @@ compiler.err.unreachable.stmt=\u65E0\u6CD5\u8BBF\u95EE\u7684\u8BED\u53E5 compiler.err.not.exhaustive=switch \u8868\u8FBE\u5F0F\u4E0D\u5305\u542B\u6240\u6709\u53EF\u80FD\u7684\u8F93\u5165\u503C +compiler.err.not.exhaustive.statement=\u5E76\u975E\u6240\u6709\u53EF\u80FD\u7684\u8F93\u5165\u503C\u90FD\u5305\u542B\u5728 switch \u8BED\u53E5\u4E2D + compiler.err.initializer.must.be.able.to.complete.normally=\u521D\u59CB\u5316\u7A0B\u5E8F\u5FC5\u987B\u80FD\u591F\u6B63\u5E38\u5B8C\u6210 compiler.err.initializer.not.allowed=\u63A5\u53E3\u4E2D\u4E0D\u5141\u8BB8\u6709\u521D\u59CB\u5316\u7A0B\u5E8F @@ -1006,7 +1025,7 @@ compiler.misc.varargs.trustme.on.reifiable.varargs=Varargs \u5143\u7D20\u7C7B\u5 compiler.err.instanceof.reifiable.not.safe={0} \u65E0\u6CD5\u5B89\u5168\u5730\u8F6C\u6362\u4E3A {1} # 0: type, 1: type -compiler.err.instanceof.pattern.no.subtype=\u6A21\u5F0F\u7C7B\u578B {0} \u662F\u8868\u8FBE\u5F0F\u7C7B\u578B {1} \u7684\u5B50\u7C7B\u578B +compiler.err.instanceof.pattern.no.subtype=\u8868\u8FBE\u5F0F\u7C7B\u578B {0} \u662F\u6A21\u5F0F\u7C7B\u578B {1} \u7684\u5B50\u7C7B\u578B # 0: symbol compiler.misc.varargs.trustme.on.non.varargs.meth=\u65B9\u6CD5 {0} \u4E0D\u662F varargs \u65B9\u6CD5\u3002 @@ -1073,12 +1092,12 @@ compiler.err.locn.invalid.arg.for.xpatch=--patch-module \u9009\u9879\u7684\u53C2 compiler.err.file.sb.on.source.or.patch.path.for.module=\u6587\u4EF6\u5E94\u5728\u6E90\u8DEF\u5F84\u6216\u6A21\u5757\u7684\u8865\u4E01\u7A0B\u5E8F\u8DEF\u5F84\u4E2D +compiler.err.no.java.lang=\u5728\u5E73\u53F0\u7C7B\u4E2D\u627E\u4E0D\u5230\u7A0B\u5E8F\u5305 java.lang + ##### # Fatal Errors -compiler.misc.fatal.err.no.java.lang=\u81F4\u547D\u9519\u8BEF: \u5728\u7C7B\u8DEF\u5F84\u6216\u5F15\u5BFC\u7C7B\u8DEF\u5F84\u4E2D\u627E\u4E0D\u5230\u7A0B\u5E8F\u5305 java.lang - # 0: name compiler.misc.fatal.err.cant.locate.meth=\u81F4\u547D\u9519\u8BEF: \u627E\u4E0D\u5230\u65B9\u6CD5{0} @@ -1168,19 +1187,21 @@ compiler.note.unchecked.filename.additional={0}\u8FD8\u6709\u672A\u7ECF\u68C0\u6 compiler.note.unchecked.plural.additional=\u67D0\u4E9B\u8F93\u5165\u6587\u4EF6\u8FD8\u4F7F\u7528\u4E86\u672A\u7ECF\u68C0\u67E5\u6216\u4E0D\u5B89\u5168\u7684\u64CD\u4F5C\u3002 -# 0: file name -compiler.note.preview.filename={0} \u4F7F\u7528\u9884\u89C8\u8BED\u8A00\u529F\u80FD\u3002 +# 0: file name, 1: source +compiler.note.preview.filename={0} \u4F7F\u7528 Java SE {1} \u7684\u9884\u89C8\u529F\u80FD\u3002 -compiler.note.preview.plural=\u67D0\u4E9B\u8F93\u5165\u6587\u4EF6\u4F7F\u7528\u9884\u89C8\u8BED\u8A00\u529F\u80FD\u3002 +# 0: source +compiler.note.preview.plural=\u67D0\u4E9B\u8F93\u5165\u6587\u4EF6\u4F7F\u7528 Java SE {0} \u7684\u9884\u89C8\u529F\u80FD\u3002 # The following string may appear after one of the above deprecation # messages. compiler.note.preview.recompile=\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u8BF7\u4F7F\u7528 -Xlint:preview \u91CD\u65B0\u7F16\u8BD1\u3002 -# 0: file name -compiler.note.preview.filename.additional={0} \u8FD8\u4F7F\u7528\u9884\u89C8\u8BED\u8A00\u529F\u80FD\u3002 +# 0: file name, 1: source +compiler.note.preview.filename.additional={0} \u8FD8\u4F7F\u7528 Java SE {1} \u7684\u9884\u89C8\u529F\u80FD\u3002 -compiler.note.preview.plural.additional=\u67D0\u4E9B\u8F93\u5165\u6587\u4EF6\u8FD8\u4F7F\u7528\u9884\u89C8\u8BED\u8A00\u529F\u80FD\u3002 +# 0: source +compiler.note.preview.plural.additional=\u67D0\u4E9B\u8F93\u5165\u6587\u4EF6\u8FD8\u4F7F\u7528 Java SE {0} \u7684\u9884\u89C8\u529F\u80FD\u3002 # Notes related to annotation processing @@ -1269,6 +1290,8 @@ compiler.warn.dir.path.element.not.directory=\u9519\u8BEF\u7684\u8DEF\u5F84\u514 # 0: symbol, 1: symbol, 2: symbol compiler.warn.missing-explicit-ctor=\u5BFC\u51FA\u7684\u7A0B\u5E8F\u5305 {1} \u4E2D\u7684\u7C7B {0} \u672A\u58F0\u660E\u663E\u5F0F\u6784\u9020\u5668\uFF0C\u56E0\u6B64\u5C06\u5411\u6A21\u5757 {2} \u7684\u5BA2\u6237\u673A\u516C\u5F00\u9ED8\u8BA4\u6784\u9020\u5668 +compiler.warn.strictfp=\u4ECE\u53D1\u884C\u7248 17 \u5F00\u59CB\uFF0C\u6240\u6709\u6D6E\u70B9\u8868\u8FBE\u5F0F\u90FD\u7ECF\u8FC7\u4E25\u683C\u8BA1\u7B97\uFF0C\u4E0D\u9700\u8981 ''strictfp'' + compiler.warn.finally.cannot.complete=finally \u5B50\u53E5\u65E0\u6CD5\u6B63\u5E38\u5B8C\u6210 # 0: name @@ -1284,10 +1307,13 @@ compiler.warn.has.been.deprecated={1}\u4E2D\u7684{0}\u5DF2\u8FC7\u65F6 compiler.warn.has.been.deprecated.for.removal={1} \u4E2D\u7684 {0} \u5DF2\u8FC7\u65F6, \u4E14\u6807\u8BB0\u4E3A\u5F85\u5220\u9664 # 0: symbol -compiler.warn.is.preview={0} \u662F\u67D0\u9884\u89C8\u529F\u80FD\u4E2D\u7684\u4E00\u4E2A API +compiler.warn.is.preview={0} \u662F\u9884\u89C8 API\uFF0C\u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002 # 0: symbol -compiler.err.is.preview={0} \u662F\u67D0\u9884\u89C8\u529F\u80FD\u4E2D\u7684\u4E00\u4E2A API +compiler.err.is.preview={0} \u662F\u9884\u89C8 API\uFF0C\u9ED8\u8BA4\u60C5\u51B5\u4E0B\u5904\u4E8E\u7981\u7528\u72B6\u6001\u3002\n\uFF08\u8BF7\u4F7F\u7528 --enable-preview \u4EE5\u542F\u7528\u9884\u89C8 API\uFF09 + +# 0: symbol +compiler.warn.is.preview.reflective={0} \u662F\u53CD\u5C04\u9884\u89C8 API\uFF0C\u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002 # 0: symbol compiler.warn.has.been.deprecated.module=\u6A21\u5757 {0} \u5DF2\u8FC7\u65F6 @@ -1303,6 +1329,11 @@ compiler.warn.illegal.char.for.encoding=\u7F16\u7801{0}\u7684\u4E0D\u53EF\u6620\ # 0: symbol compiler.warn.improper.SVUID=\u5FC5\u987B\u5728\u7C7B{0}\u4E2D\u5C06 serialVersionUID \u58F0\u660E\u4E3A static final +compiler.warn.improper.SPF=serialPersistentFields \u5FC5\u987B\u58F0\u660E\u4E3A private static final \u624D\u80FD\u751F\u6548 + +compiler.warn.SPF.null.init=serialPersistentFields \u5982\u679C\u521D\u59CB\u5316\u4E3A\u7A7A\u503C\uFF0C\u5219\u65E0\u6548\u3002\n\u8BF7\u521D\u59CB\u5316\u4E3A\u7A7A\u6570\u7EC4\u4EE5\u6307\u793A\u6CA1\u6709\u5B57\u6BB5 + + # 0: type, 1: type compiler.warn.inexact.non-varargs.call=\u6700\u540E\u4E00\u4E2A\u53C2\u6570\u4F7F\u7528\u4E86\u4E0D\u51C6\u786E\u7684\u53D8\u91CF\u7C7B\u578B\u7684 varargs \u65B9\u6CD5\u7684\u975E varargs \u8C03\u7528; \n\u5BF9\u4E8E varargs \u8C03\u7528, \u5E94\u4F7F\u7528 {0}\n\u5BF9\u4E8E\u975E varargs \u8C03\u7528, \u5E94\u4F7F\u7528 {1}, \u8FD9\u6837\u4E5F\u53EF\u4EE5\u6291\u5236\u6B64\u8B66\u544A @@ -1315,9 +1346,67 @@ compiler.warn.unreachable.catch.1=catch \u5B50\u53E5\u65E0\u6CD5\u8BBF\u95EE\n\u # 0: symbol compiler.warn.long.SVUID=serialVersionUID \u5728\u7C7B{0}\u4E2D\u5FC5\u987B\u662F long \u7C7B\u578B +compiler.warn.OSF.array.SPF=serialPersistentFields \u7684\u7C7B\u578B\u5FC5\u987B\u4E3A java.io.ObjectStreamField[] \u624D\u80FD\u751F\u6548 + # 0: symbol compiler.warn.missing.SVUID=\u53EF\u5E8F\u5217\u5316\u7C7B{0}\u6CA1\u6709 serialVersionUID \u7684\u5B9A\u4E49 +# 0: name +compiler.warn.serializable.missing.access.no.arg.ctor=\u65E0\u6CD5\u8BBF\u95EE\u7B2C\u4E00\u4E2A\u4E0D\u53EF\u5E8F\u5217\u5316\u8D85\u7C7B {0} \u4E2D\u7684\u65E0\u53C2\u6570\u6784\u9020\u5668 + +# 0: name +compiler.warn.serial.method.not.private=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u672A\u58F0\u660E\u4E3A private + +# 0: name +compiler.warn.serial.concrete.instance.method=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5FC5\u987B\u662F\u5177\u4F53\u7684\u5B9E\u4F8B\u65B9\u6CD5\u624D\u80FD\u751F\u6548\uFF0C\u65E2\u4E0D\u80FD\u662F\u62BD\u8C61\u65B9\u6CD5\u4E5F\u4E0D\u80FD\u662F\u9759\u6001\u65B9\u6CD5 + +# 0: name +compiler.warn.serial.method.static=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u58F0\u660E\u4E3A static\uFF1B\u5FC5\u987B\u6539\u4E3A\u5B9E\u4F8B\u65B9\u6CD5\u624D\u80FD\u6709\u6548 + +# 0: name +compiler.warn.serial.method.no.args=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5FC5\u987B\u6CA1\u6709\u53C2\u6570\u624D\u80FD\u751F\u6548 + +# 0: name, 1: number +compiler.warn.serial.method.one.arg=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5FC5\u987B\u53EA\u6709\u4E00\u4E2A\u53C2\u6570\uFF08\u800C\u975E {1} \u4E2A\u53C2\u6570\uFF09\u624D\u80FD\u751F\u6548 + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.parameter.type=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u7684\u552F\u4E00\u53C2\u6570\u7684\u7C7B\u578B\u5FC5\u987B\u4E3A {1}\uFF08\u800C\u975E {2}\uFF09\u624D\u80FD\u751F\u6548 + +# 0: name, 1: type, 2: type +compiler.warn.serial.method.unexpected.return.type=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u662F\u7528\u8FD4\u56DE\u7C7B\u578B {1}\uFF08\u800C\u4E0D\u662F\u9884\u671F\u7C7B\u578B {2}\uFF09\u58F0\u660E\u7684\u3002\n\u5982\u58F0\u660E\u7684\u90A3\u6837\uFF0C\u8BE5\u65B9\u6CD5\u5BF9\u5E8F\u5217\u5316\u65E0\u6548 + +# 0: name, 1: type +compiler.warn.serial.method.unexpected.exception=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u58F0\u660E\u4E3A\u629B\u51FA\u610F\u5916\u7C7B\u578B {1} + +compiler.warn.ineffectual.serial.field.interface=serialPersistentFields \u5728\u63A5\u53E3\u4E2D\u65E0\u6548 + +# 0: string +compiler.warn.ineffectual.serial.field.enum=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u5B57\u6BB5 {0} \u5728\u679A\u4E3E\u7C7B\u4E2D\u65E0\u6548 + +# 0: string +compiler.warn.ineffectual.serial.method.enum=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5728\u679A\u4E3E\u7C7B\u4E2D\u65E0\u6548 + +compiler.warn.ineffectual.serial.field.record=serialPersistentFields \u5728\u8BB0\u5F55\u7C7B\u4E2D\u65E0\u6548 + +# 0: string +compiler.warn.ineffectual.serial.method.record=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5728\u8BB0\u5F55\u7C7B\u4E2D\u65E0\u6548 + +# 0: name +compiler.warn.ineffectual.serial.method.externalizable=\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u65B9\u6CD5 {0} \u5728\u53EF\u5916\u90E8\u5316\u7684\u7C7B\u4E2D\u65E0\u6548 + +compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields \u5728\u53EF\u5916\u90E8\u5316\u7684\u7C7B\u4E2D\u65E0\u6548 + +compiler.warn.externalizable.missing.public.no.arg.ctor=\u53EF\u5916\u90E8\u5316\u7684\u7C7B\u9700\u8981\u4E00\u4E2A\u516C\u5171\u7684\u65E0\u53C2\u6570\u6784\u9020\u5668 + +compiler.warn.non.serializable.instance.field=\u53EF\u5E8F\u5217\u5316\u7C7B\u7684\u975E\u77AC\u65F6\u5B9E\u4F8B\u5B57\u6BB5\u662F\u7528\u4E0D\u53EF\u5E8F\u5217\u5316\u7684\u7C7B\u578B\u58F0\u660E\u7684 + +# 0: type +compiler.warn.non.serializable.instance.field.array=\u53EF\u5E8F\u5217\u5316\u7C7B\u7684\u975E\u77AC\u65F6\u5B9E\u4F8B\u5B57\u6BB5\u662F\u7528\u5177\u6709\u4E0D\u53EF\u5E8F\u5217\u5316\u57FA\u672C\u7EC4\u4EF6\u7C7B\u578B {0} \u7684\u6570\u7EC4\u58F0\u660E\u7684 + +compiler.warn.non.private.method.weaker.access=\u5728\u63A5\u53E3\u4E2D\u58F0\u660E\u4E3A non-private \u7684\u5E8F\u5217\u5316\u76F8\u5173\u65B9\u6CD5\u5C06\u963B\u6B62\n\u5B9E\u73B0\u63A5\u53E3\u7684\u7C7B\u5C06\u65B9\u6CD5\u58F0\u660E\u4E3A private + +compiler.warn.default.ineffective=\u5B9E\u73B0\u7C7B\u7684\u5E8F\u5217\u5316\u4E0D\u4F1A\u8FD0\u884C\u63A5\u53E3\u4E2D\u4E0E\u5E8F\u5217\u5316\u76F8\u5173\u7684\u9ED8\u8BA4\u65B9\u6CD5 + # 0: symbol, 1: symbol, 2: symbol, 3: symbol compiler.warn.potentially.ambiguous.overload={1} \u4E2D\u7684 {0} \u53EF\u80FD\u4E0E {3} \u4E2D\u7684 {2} \u6DF7\u6DC6 @@ -1404,7 +1493,7 @@ compiler.warn.proc.suspicious.class.name=\u6B63\u5728\u4E3A\u540D\u79F0\u4EE5{1} compiler.warn.proc.file.create.last.round=\u5C06\u4E0D\u5BF9\u5728\u6700\u540E\u4E00\u4E2A\u5FAA\u73AF\u4E2D\u521B\u5EFA\u7684\u7C7B\u578B\u4E3A ''{0}'' \u7684\u6587\u4EF6\u8FDB\u884C\u6CE8\u91CA\u5904\u7406\u3002 # 0: string, 1: string -compiler.warn.proc.malformed.supported.string=\u5904\u7406\u7A0B\u5E8F ''{1}'' \u4E3A\u652F\u6301\u7684\u6CE8\u91CA\u7C7B\u578B\u8FD4\u56DE\u683C\u5F0F\u9519\u8BEF\u7684\u5B57\u7B26\u4E32 ''{0}'' +compiler.warn.proc.malformed.supported.string=\u5904\u7406\u7A0B\u5E8F ''{1}'' \u4E3A\u652F\u6301\u7684\u6CE8\u91CA\u63A5\u53E3\u8FD4\u56DE\u683C\u5F0F\u9519\u8BEF\u7684\u5B57\u7B26\u4E32 ''{0}'' # 0: set of string compiler.warn.proc.annotations.without.processors=\u6CA1\u6709\u5904\u7406\u7A0B\u5E8F\u8981\u4F7F\u7528\u4EE5\u4E0B\u4EFB\u4F55\u6CE8\u91CA: {0} @@ -1416,10 +1505,10 @@ compiler.warn.proc.processor.incompatible.source.version=\u6765\u81EA\u6CE8\u91C compiler.warn.proc.duplicate.option.name=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F ''{1}'' \u8FD4\u56DE\u91CD\u590D\u7684\u652F\u6301\u7684\u9009\u9879 ''{0}'' # 0: string, 1: string -compiler.warn.proc.duplicate.supported.annotation=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F ''{1}'' \u8FD4\u56DE\u91CD\u590D\u7684\u652F\u6301\u7684\u6CE8\u91CA\u7C7B\u578B ''{0}'' +compiler.warn.proc.duplicate.supported.annotation=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F ''{1}'' \u8FD4\u56DE\u91CD\u590D\u7684\u53D7\u652F\u6301\u6CE8\u91CA\u63A5\u53E3 ''{0}'' # 0: string -compiler.warn.proc.redundant.types.with.wildcard=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F ''{0}'' \u91CD\u590D\u652F\u6301 ''*'' \u548C\u5176\u4ED6\u6CE8\u91CA\u7C7B\u578B +compiler.warn.proc.redundant.types.with.wildcard=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F ''{0}'' \u91CD\u590D\u652F\u6301 ''*'' \u548C\u5176\u4ED6\u6CE8\u91CA\u63A5\u53E3 compiler.warn.proc.proc-only.requested.no.procs=\u5728\u672A\u8BF7\u6C42\u7F16\u8BD1\u7684\u60C5\u51B5\u4E0B\u8FDB\u884C\u6CE8\u91CA\u5904\u7406, \u4F46\u627E\u4E0D\u5230\u5904\u7406\u7A0B\u5E8F\u3002 @@ -1475,6 +1564,8 @@ compiler.warn.deprecated.annotation.has.no.effect=@Deprecated \u6CE8\u91CA\u5BF9 # 0: string compiler.warn.invalid.path=\u65E0\u6548\u6587\u4EF6\u540D: {0} +compiler.warn.doclint.not.available=\u6CA1\u6709 doclint \u670D\u52A1\u63D0\u4F9B\u65B9\u53EF\u7528 + # 0: string compiler.err.invalid.path=\u65E0\u6548\u6587\u4EF6\u540D: {0} @@ -1577,8 +1668,6 @@ compiler.err.enum.constant.expected=\u6B64\u5904\u9700\u8981\u679A\u4E3E\u5E38\u compiler.err.enum.constant.not.expected=\u6B64\u5904\u4E0D\u9700\u8981\u679A\u4E3E\u5E38\u91CF ## The following are related in form, but do not easily fit the above paradigm. -compiler.err.expected.module=\u9700\u8981 ''module'' - compiler.err.expected.module.or.open=\u9700\u8981 ''module'' \u6216 ''open'' compiler.err.dot.class.expected=\u9700\u8981 ''.class'' @@ -2103,6 +2192,10 @@ compiler.misc.feature.records=\u8BB0\u5F55 compiler.misc.feature.sealed.classes=\u5BC6\u5C01\u7C7B +compiler.misc.feature.case.null=switch case \u4E2D\u7684\u7A7A\u503C + +compiler.misc.feature.pattern.switch=switch \u8BED\u53E5\u4E2D\u7684\u6A21\u5F0F + compiler.warn.underscore.as.identifier=\u4ECE\u53D1\u884C\u7248 9 \u5F00\u59CB, ''_'' \u4E3A\u5173\u952E\u5B57, \u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26 compiler.err.underscore.as.identifier=\u4ECE\u53D1\u884C\u7248 9 \u5F00\u59CB, ''_'' \u4E3A\u5173\u952E\u5B57, \u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26 @@ -2174,6 +2267,28 @@ compiler.note.deferred.method.inst=\u65B9\u6CD5 {0} \u7684\u5EF6\u8FDF\u5B9E\u4F # 0: symbol compiler.note.verbose.l2m.deduplicate=\u6B63\u5728\u5BF9 lambda \u51FD\u6570\u5B9E\u73B0\u65B9\u6CD5 {0} \u8FDB\u884C\u91CD\u590D\u6570\u636E\u5220\u9664 +######################################## +# Diagnostics for method reference search +# results used by Resolve (debug only) +######################################## + +# 0: fragment, 1: string, 2: number +compiler.note.method.ref.search.results.multi={1} \u7684 {0} \u641C\u7D22\u7ED3\u679C\uFF0C\u6709 {2} \u4E2A\n\u6700\u660E\u786E\u7684\u9002\u7528\u5019\u9009\u9879\uFF1A + +# 0: number, 1: fragment, 2: symbol +compiler.misc.applicable.method.found.2=\u627E\u5230\u7684\u7B2C {0} \u4E2A\u9002\u7528\u65B9\u6CD5\uFF1A{1} {2} + +# 0: number, 1: fragment, 2: symbol, 3: message segment +compiler.misc.applicable.method.found.3=\u627E\u5230\u7684\u7B2C {0} \u4E2A\u9002\u7528\u65B9\u6CD5\uFF1A{1} {2}\n({3}) + +compiler.misc.static=\u9759\u6001 + +compiler.misc.non.static=\u975E\u9759\u6001 + +compiler.misc.bound=\u7ED1\u5B9A + +compiler.misc.unbound=\u672A\u7ED1\u5B9A + ######################################## # Diagnostics for where clause implementation # used by the RichDiagnosticFormatter. @@ -2260,7 +2375,7 @@ compiler.err.dc.no.tag.name='@' \u540E\u6CA1\u6709\u6807\u8BB0\u540D compiler.err.dc.gt.expected=\u9700\u8981 ''>'' -compiler.err.dc.ref.bad.parens=\u5F15\u7528\u4E2D\u7F3A\u5C11 '')'' +compiler.err.dc.ref.bad.parens=\u62EC\u53F7\u4E4B\u540E\u51FA\u73B0\u610F\u5916\u7684\u6587\u672C compiler.err.dc.ref.syntax.error=\u5F15\u7528\u4E2D\u51FA\u73B0\u8BED\u6CD5\u9519\u8BEF @@ -2274,6 +2389,8 @@ compiler.err.dc.unterminated.signature=\u672A\u7EC8\u6B62\u7684\u7B7E\u540D compiler.err.dc.unterminated.string=\u672A\u7EC8\u6B62\u7684\u5B57\u7B26\u4E32 +compiler.err.dc.ref.annotations.not.allowed=\u4E0D\u5141\u8BB8\u4F7F\u7528\u6CE8\u91CA + ### # errors related to modules @@ -2450,8 +2567,6 @@ compiler.err.illegal.argument.for.option={0} \u7684\u53C2\u6570\u975E\u6CD5: {1} compiler.err.match.binding.exists=\u5C1D\u8BD5\u91CD\u65B0\u5B9A\u4E49\u73B0\u6709\u7684\u5339\u914D\u7ED1\u5B9A\uFF0C\u8FD9\u662F\u975E\u6CD5\u7684 -compiler.err.switch.null.not.allowed=case \u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528\u7A7A\u6807\u7B7E - compiler.err.switch.case.unexpected.statement=case \u4E2D\u5B58\u5728\u610F\u5916\u8BED\u53E5\uFF0C\u5E94\u4E3A\u8868\u8FBE\u5F0F\u3001\u5757\u6216\u629B\u51FA\u8BED\u53E5 compiler.err.switch.mixing.case.types=\u5728 switch \u4E2D\u4F7F\u7528\u4E86\u4E0D\u540C case \u7C7B\u578B @@ -2664,5 +2779,7 @@ compiler.err.preview.not.latest=\u6E90\u53D1\u884C\u7248 {0} \u4E0E --enable-pre compiler.err.preview.without.source.or.release=--enable-preview \u5FC5\u987B\u4E0E -source \u6216 --release \u4E00\u8D77\u4F7F\u7528 -compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\u5C1D\u8BD5\u5728\u57FA\u4E8E\u503C\u7684\u7C7B\u7684\u5B9E\u4F8B\u4E0A\u540C\u6B65 +# 0: kind name, 1: symbol +compiler.warn.declared.using.preview={0} {1} \u662F\u4F7F\u7528\u9884\u89C8\u529F\u80FD\u58F0\u660E\u7684\uFF0C\u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002 +compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\u5C1D\u8BD5\u5728\u57FA\u4E8E\u503C\u7684\u7C7B\u7684\u5B9E\u4F8B\u4E0A\u540C\u6B65 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..85b76234891ba3d2a6798ac2255db83282a65207 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -0,0 +1,228 @@ +# +# Copyright (c) 1999, 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. +# + +## standard options + +javac.opt.g=Generiert alle Debugginginformationen +javac.opt.g.none=Generiert keine Debugginginformationen +javac.opt.g.lines.vars.source=Generiert nur einige Debugginginformationen +javac.opt.nowarn=Generiert keine Warnungen +javac.opt.verbose=Gibt Nachrichten zu den Compilervorg\u00E4ngen aus +javac.opt.deprecation=Gibt Quellspeicherorte aus, wo veraltete APIs verwendet werden +javac.opt.classpath=Gibt an, wo sich die Benutzerklassendateien und Annotationsprozessoren befinden +javac.opt.modulepath=Gibt an, wo sich die Anwendungsmodule befinden +javac.opt.sourcepath=Gibt an, wo sich die Eingabequelldateien befinden +javac.opt.m=Kompiliert nur die angegebenen Module und pr\u00FCft die Zeitstempel +javac.opt.modulesourcepath=Gib an, wo sich die Eingabequelldateien f\u00FCr mehrere Module befinden +javac.opt.bootclasspath=Setzt den Speicherort der Bootstrap-Klassendateien au\u00DFer Kraft +javac.opt.system=Setzt den Speicherort der Systemmodule au\u00DFer Kraft +javac.opt.upgrademodulepath=Setzt den Speicherort der upgradef\u00E4higen Module au\u00DFer Kraft +javac.opt.endorseddirs=Setzt den Speicherort der unterst\u00FCtzten Standardpfade au\u00DFer Kraft +javac.opt.extdirs=Setzt den Speicherort der installierten Erweiterungen au\u00DFer Kraft +javac.opt.processorpath=Gibt an, wo sich die Annotationsprozessoren befinden +javac.opt.processormodulepath=Gibt einen Modulpfad an, wo sich die Annotationsprozessoren befinden +javac.opt.processor=Namen der auszuf\u00FChrenden Annotationsprozessoren; Standard-Discovery-Prozess wird umgangen +javac.opt.parameters=Generiert Metadaten zur Reflexion auf Methodenparameter +javac.opt.proc.none.only=Steuert, wo die Verarbeitung von Annotationen und/oder die Kompilierung ausgef\u00FChrt wird +javac.opt.d=Gibt an, wo generierte Klassendateien abgelegt werden +javac.opt.sourceDest=Gibt an, wo generierte Quelldateien abgelegt werden +javac.opt.headerDest=Gibt an, wo generierte native Headerdateien abgelegt werden +javac.opt.J=\u00DCbergibt direkt an das Laufzeitsystem +javac.opt.encoding=Gibt die von den Quelldateien verwendete Zeichencodierung an +javac.opt.profile=Vergewissern Sie sich, dass die verwendete API im angegebenen Profil verf\u00FCgbar ist +javac.opt.target=Generiert Klassendateien, die sich f\u00FCr das angegebene Java SE-Release eignen. Unterst\u00FCtzte Releases: {0} +javac.opt.release=Kompiliert f\u00FCr das angegebene Java SE-Release. Unterst\u00FCtzte Releases: {0} +javac.opt.source=Liefert Quellkompatibilit\u00E4t mit dem angegebenen Release von Java SE. Unterst\u00FCtzte Releases: {0} +javac.opt.Werror=Kompilierung beenden, wenn Warnungen auftreten +javac.opt.A=Optionen zur \u00DCbergabe an die Annotationsprozessoren +javac.opt.implicit=Gibt an, ob Klassendateien f\u00FCr implizit referenzierte Dateien generiert werden oder nicht +javac.opt.pkginfo=Gibt an, wie package-info-Dateien behandelt werden sollen +javac.opt.multi-release=Gibt an, welches Release in Multi-Release-JAR-Dateien verwendet werden soll +javac.opt.arg.class= +javac.opt.arg.class.list=[,,...] +javac.opt.arg.flag= +javac.opt.arg.key.equals.value=key[=value] +javac.opt.arg.path= +javac.opt.arg.mspath= +javac.opt.arg.m=(,)* +javac.opt.arg.jdk=|none +javac.opt.arg.dirs= +javac.opt.arg.directory= +javac.opt.arg.encoding= +javac.opt.arg.profile= +javac.opt.arg.release= +javac.opt.arg.release= +javac.opt.arg.number= +javac.opt.plugin=Der Name und optional die Argumente f\u00FCr die Ausf\u00FChrung eines Plug-ins +javac.opt.arg.plugin="name args" +javac.opt.arg.multi-release= +javac.opt.arg.default.module.for.created.files= + +## extended options + +javac.opt.maxerrs=Legt die maximale Anzahl der zu auszugebenden Fehler fest +javac.opt.maxwarns=Legt die maximale Anzahl der auszugebenden Warnungen fest +javac.opt.nogj=Akzeptiert keine Generics in der Sprache +javac.opt.moreinfo=Gibt erweiterte Informationen f\u00FCr Typvariablen aus +javac.opt.printsearch=Gibt Informationen dazu aus, wo Klassendateien gesucht werden +javac.opt.prompt=Stoppt nach jedem Fehler +javac.opt.s=Gibt Java-Quellen statt Klassendateien aus +javac.opt.version=Versionsinformationen +javac.opt.arg.pathname= +javac.opt.arg.file= +javac.opt.Xbootclasspath.p=Dem Bootstrap Classpath voranstellen +javac.opt.Xbootclasspath.a=An Bootstrap Classpath anh\u00E4ngen +javac.opt.Xlint=Aktiviert die empfohlenen Warnungen +javac.opt.Xlint.all=Alle Warnungen aktivieren +javac.opt.Xlint.none=Alle Warnungen deaktivieren +#L10N: do not localize: -Xlint +javac.opt.arg.Xlint=(,)* +javac.opt.Xlint.custom=Warnungen, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt.\nStellen Sie einem Schl\u00FCssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie --help-lint, um die unterst\u00FCtzten Schl\u00FCssel zu sehen. +javac.opt.Xlint.desc.auxiliaryclass=Warnt vor Auxiliary-Klassen, die in einer Quelldatei verborgen sind und aus anderen Dateien heraus verwendet werden. + +javac.opt.Xlint.desc.cast=Warnt vor unn\u00F6tigen Umwandlungen mit Cast. + +javac.opt.Xlint.desc.classfile=Warnt vor Problemen im Zusammenhang mit Klassendateiinhalten. + +javac.opt.Xlint.desc.missing-explicit-ctor=Warnt vor fehlenden expliziten Konstruktoren in \u00F6ffentlichen und gesch\u00FCtzten Klassen in exportierten Packages. + +javac.opt.Xlint.desc.deprecation=Warnt vor der Verwendung veralteter Elemente. + +javac.opt.Xlint.desc.dep-ann=Warnt vor Elementen, die in JavaDoc als veraltet markiert sind, jedoch nicht mit der Annotation @Deprecated versehen sind. + +javac.opt.Xlint.desc.divzero=Warnt vor Division durch Ganzzahlkonstante 0. + +javac.opt.Xlint.desc.empty=Warnt vor leerer Anweisung nach "if". + +javac.opt.Xlint.desc.exports=Warnt vor Problemen in Bezug auf Modulexporte. + +javac.opt.Xlint.desc.fallthrough=Warnt vor Weitergabe von einem Case einer Switch-Anweisung zum n\u00E4chsten. + +javac.opt.Xlint.desc.finally=Warnt vor Finally-Klauseln, die nicht normal beendet werden. + +javac.opt.Xlint.desc.module=Warnt vor Problemen im Zusammenhang mit dem Modulsystem. + +javac.opt.Xlint.desc.opens=Warnt vor Problemen in Bezug auf Modul\u00F6ffnungen. + +javac.opt.Xlint.desc.options=Warnt vor Problemen im Zusammenhang mit der Verwendung von Befehlszeilenoptionen. + +javac.opt.Xlint.desc.overloads=Warnt vor Problemen in Bezug auf Methoden\u00FCberladung. + +javac.opt.Xlint.desc.overrides=Warnt vor Problemen in Bezug auf Methodenau\u00DFerkraftsetzung. + +javac.opt.Xlint.desc.path=Warnt vor ung\u00FCltigen Pfadelementen in der Befehlszeile. + +javac.opt.Xlint.desc.processing=Warnt vor Problemen in Bezug auf die Annotationsverarbeitung. + +javac.opt.Xlint.desc.rawtypes=Warnt vor der Verwendung von Raw-Typen. + +javac.opt.Xlint.desc.removal=Warnt vor der Verwendung einer API, die zum Entfernen markiert wurde. + +javac.opt.Xlint.desc.requires-automatic=Warnt vor der Verwendung automatischer Module in den "Requires"-Klauseln. + +javac.opt.Xlint.desc.requires-transitive-automatic=Warnt vor automatischen Modulen in "requires transitive". + +javac.opt.Xlint.desc.serial=Warnt vor serialisierbaren Klassen, die kein serialVersionUID-Feld haben. \n Warnt auch vor anderen verd\u00E4chtigen Deklarationen in serialisierbaren und externalisierbaren Klassen und Schnittstellen. + +javac.opt.Xlint.desc.static=Warnt vor Zugriff auf ein statisches Mitglied mit einer Instanz. + +javac.opt.Xlint.desc.strictfp=Warnt vor unn\u00F6tiger Verwendung des strictfp-Modifizierers. + +javac.opt.Xlint.desc.text-blocks=Warnt vor inkonsistenten Leerzeichen in Textblockeinr\u00FCckung. + +javac.opt.Xlint.desc.try=Warnt vor Problemen im Zusammenhang mit try-Bl\u00F6cken (d.h. try-with-resources). + +javac.opt.Xlint.desc.unchecked=Warnt vor deaktivierten Vorg\u00E4ngen. + +javac.opt.Xlint.desc.varargs=Warnt vor m\u00F6glicherweise nicht sicheren vararg-Methoden. + +javac.opt.Xlint.desc.preview=Warnt vor Verwendung von Vorschausprachfeatures. + +javac.opt.Xlint.desc.synchronization=Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen. + +javac.opt.Xdoclint=Empfohlene Pr\u00FCfungen f\u00FCr Probleme in javadoc-Kommentaren aktivieren +# L10N: do not localize: all none +javac.opt.Xdoclint.subopts = (all|none|[-])[/] + +# L10N: do not localize: accessibility html missing reference syntax +# L10N: do not localize: public protected package private +javac.opt.Xdoclint.custom=Aktiviert oder deaktiviert bestimmte Pr\u00FCfungen auf Probleme in javadoc-Kommentaren,\nwobei f\u00FCr accessibility, html, missing, reference oder syntax\nund f\u00FCr public, protected, package oder private steht. + +javac.opt.Xdoclint.package.args = [-](,[-])* + +javac.opt.Xdoclint.package.desc=Aktiviert oder deaktiviert Pr\u00FCfungen in bestimmten Packages. Jedes ist entweder der\nqualifizierte Name eines Packages oder ein Namenspr\u00E4fix, gefolgt von ".*", und bezieht sich auf\nalle Subpackages des angegebenen Packages. Jedem Package kann \nvorangestellt werden, um Pr\u00FCfungen f\u00FCr die angegebenen Packages zu deaktivieren. + +javac.opt.Xstdout=Leitet die Standardausgabe um +javac.opt.X=Gibt Hilfe zu zus\u00E4tzlichen Optionen aus +javac.opt.help=Gibt diese Hilfemeldung aus +javac.opt.help.lint=Gibt die unterst\u00FCtzten Schl\u00FCssel f\u00FCr -Xlint aus +javac.opt.help.lint.header=Die unterst\u00FCtzten Schl\u00FCssel f\u00FCr -Xlint sind: +javac.opt.print=Gibt eine Textdarstellung der angegebenen Typen aus +javac.opt.printRounds=Gibt Informationen zu Durchl\u00E4ufen der Annotationsverarbeitung aus +javac.opt.printProcessorInfo=Gibt Informationen dazu aus, welche Annotationen ein Prozessor verarbeiten soll +javac.opt.userpathsfirst=Durchsucht classpath und sourcepath vor anstatt nach bootclasspath nach Klassen +javac.opt.prefer=Gibt an, welche Datei gelesen werden soll, wenn sowohl eine Quell- als auch eine Klassendatei f\u00FCr eine implizit kompilierte Klasse gefunden werden +javac.opt.preview=Aktiviert Vorschausprachfeatures. Wird in Verbindung mit -source oder --release verwendet. +javac.opt.AT=Liest Optionen und Dateinamen aus Datei +javac.opt.diags=W\u00E4hlt einen Diagnosemodus aus +javac.opt.addExports=Gibt an, dass ein Package als aus seinem definierenden Modul in weitere Module oder, wenn\n ALL-UNNAMED lautet, in alle unbenannten Module exportiert betrachtet werden soll. +javac.opt.arg.addExports=/=(,)* +javac.opt.addReads=Gibt weitere Module an, die als von einem gegebenen Modul angefordert betrachtet werden sollen.\n kann ALL-UNNAMED lauten, um das unbenannte Modul anzufordern. +javac.opt.arg.addReads==(,)* +javac.opt.patch=Setzt ein Modul au\u00DFer Kraft oder erweitert es mit Klassen und Ressourcen\nin JAR-Dateien oder Verzeichnissen +javac.opt.arg.patch==(:)* +javac.opt.addmods=Root-Module, die zus\u00E4tzlich zu den anf\u00E4nglichen Modulen aufgel\u00F6st werden sollen, oder alle Module\nim Modulpfad, wenn ALL-MODULE-PATH lautet. +javac.opt.arg.addmods=(,)* +javac.opt.limitmods=Begrenzt die Gesamtzahl der beobachtbaren Module +javac.opt.arg.limitmods=(,)* +javac.opt.module.version=Gibt die Version der Module an, die kompiliert werden +javac.opt.arg.module.version= +javac.opt.inherit_runtime_environment=Vererbt Modulsystemkonfigurationsoptionen aus der Laufzeitumgebung. +javac.opt.default.module.for.created.files=Fallback-Zielmodul f\u00FCr Dateien, die von Annotationsprozessoren erstellt werden, falls keines angegeben ist oder abgeleitet werden kann. + +## messages + +javac.msg.usage.header=Verwendung: {0} ,\nwobei folgende Optionen m\u00F6glich sind: + +javac.msg.usage=Verwendung: {0} \nMit --help k\u00F6nnen Sie eine Liste der m\u00F6glichen Optionen aufrufen + +javac.msg.usage.nonstandard.footer=Diese zus\u00E4tzlichen Optionen k\u00F6nnen jederzeit ohne vorherige Ank\u00FCndigung ge\u00E4ndert werden. + +javac.msg.bug=Im Compiler ({0}) ist eine Ausnahme aufgetreten. Erstellen Sie auf der Java-Seite zum Melden von Bugs (http://bugreport.java.com) einen Bugbericht, nachdem Sie die Bugdatenbank (http://bugs.java.com) auf Duplikate gepr\u00FCft haben. Geben Sie in Ihrem Bericht Ihr Programm, die folgende Diagnose und die Parameter an, die Sie dem Java-Compiler \u00FCbergeben haben. Vielen Dank. + +javac.msg.io=\n\nEin Eingabe-/Ausgabefehler ist aufgetreten.\nDetails finden Sie im folgenden Stacktrace.\n + +javac.msg.proc.annotation.uncaught.exception=\n\nEin Annotationsprozessor hat eine nicht abgefangene Ausnahme ausgel\u00F6st.\nDetails finden Sie im folgenden Stacktrace.\n + +javac.msg.plugin.uncaught.exception=\n\nEin Plug-in hat eine nicht abgefangene Ausnahme ausgel\u00F6st.\nDetails finden Sie im folgenden Stacktrace.\n + +javac.msg.resource=\n\nDas System hat keine Ressourcen mehr.\nDetails finden Sie im folgenden Stacktrace.\n + +javac.version={0} {1} +javac.fullVersion={0} Vollversion "{1}" + +javac.msg.parameters.output=Ausgabe von javac-Parametern an: {0} + +javac.msg.parameters.output.error=Fehler beim Versuch, javac-Parameter auszugeben an: {0}. Die Parameter folgen: diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index 231bbc69df87b0e173c95a3a98c377c0cef46f3b..0628340ea2b8ce7bcc0ec122db90044df6f9828e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -99,7 +99,7 @@ javac.opt.Xlint.all=\u3059\u3079\u3066\u306E\u8B66\u544A\u3092\u6709\u52B9\u306B javac.opt.Xlint.none=\u3059\u3079\u3066\u306E\u8B66\u544A\u3092\u7121\u52B9\u306B\u3057\u307E\u3059 #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B\u8B66\u544A(\u30AB\u30F3\u30DE\u533A\u5207\u308A)\u3002\n \u6307\u5B9A\u3057\u305F\u8B66\u544A\u3092\u7121\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30AD\u30FC\u306E\u524D\u306B'-'\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\n \u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u308B\u30AD\u30FC\u306F\u6B21\u306E\u3068\u304A\u308A\u3067\u3059: +javac.opt.Xlint.custom=\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B\u8B66\u544A(\u30AB\u30F3\u30DE\u533A\u5207\u308A)\u3002\n\u6307\u5B9A\u3057\u305F\u8B66\u544A\u3092\u7121\u52B9\u306B\u3059\u308B\u306B\u306F\u3001\u30AD\u30FC\u306E\u524D\u306B'-'\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\n\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u308B\u30AD\u30FC\u3092\u8868\u793A\u3059\u308B\u306B\u306F--help-lint\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 javac.opt.Xlint.desc.auxiliaryclass=\u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3067\u975E\u8868\u793A\u306B\u306A\u3063\u3066\u3044\u308B\u304C\u4ED6\u306E\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u4F7F\u7528\u3055\u308C\u3066\u3044\u308B\u88DC\u52A9\u30AF\u30E9\u30B9\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 javac.opt.Xlint.desc.cast=\u4E0D\u8981\u306A\u30AD\u30E3\u30B9\u30C8\u306E\u4F7F\u7528\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 @@ -144,10 +144,12 @@ javac.opt.Xlint.desc.requires-automatic=requires\u53E5\u5185\u306E\u81EA\u52D5\u javac.opt.Xlint.desc.requires-transitive-automatic=requires transitive\u5185\u306E\u81EA\u52D5\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 -javac.opt.Xlint.desc.serial=\u30B7\u30EA\u30A2\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3ID\u3092\u6307\u5B9A\u3057\u306A\u3044\u76F4\u5217\u5316\u53EF\u80FD\u306A\u30AF\u30E9\u30B9\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 \n \u307E\u305F\u3001\u76F4\u5217\u5316\u53EF\u80FD\u8981\u7D20\u304B\u3089public\u4EE5\u5916\u306E\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 +javac.opt.Xlint.desc.serial=serialVersionUID\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u306A\u3044\u76F4\u5217\u5316\u53EF\u80FD\u30AF\u30E9\u30B9\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 \n \u76F4\u5217\u5316\u53EF\u80FD\u304A\u3088\u3073\u5916\u90E8\u5316\u53EF\u80FD\u30AF\u30E9\u30B9\u3068\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067\u306E\u4ED6\u306E\u8981\u6CE8\u610F\u5BA3\u8A00\u306B\u3064\u3044\u3066\u3082\u8B66\u544A\u3057\u307E\u3059\u3002 javac.opt.Xlint.desc.static=\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u4F7F\u7528\u3057\u305Fstatic\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 +javac.opt.Xlint.desc.strictfp=strictfp\u4FEE\u98FE\u5B50\u306E\u4E0D\u8981\u306A\u4F7F\u7528\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 + javac.opt.Xlint.desc.text-blocks=\u30C6\u30AD\u30B9\u30C8\u30FB\u30D6\u30ED\u30C3\u30AF\u30FB\u30A4\u30F3\u30C7\u30F3\u30C8\u5185\u306E\u4E00\u8CAB\u6027\u306E\u306A\u3044\u7A7A\u767D\u6587\u5B57\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 javac.opt.Xlint.desc.try=try\u30D6\u30ED\u30C3\u30AF(try-with-resources\u306A\u3069)\u306E\u4F7F\u7528\u306B\u95A2\u3059\u308B\u554F\u984C\u306B\u3064\u3044\u3066\u8B66\u544A\u3057\u307E\u3059\u3002 @@ -172,11 +174,11 @@ javac.opt.Xdoclint.package.args = [-](,[-])* javac.opt.Xdoclint.package.desc=\u7279\u5B9A\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3057\u307E\u3059\u3002\u5404\u306F\u3001\n\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4FEE\u98FE\u3055\u308C\u305F\u540D\u524D\u3001\u307E\u305F\u306F\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306E\u63A5\u982D\u8F9E\u306E\u5F8C\u306B''.*''\u3092\u6307\u5B9A\n(\u6307\u5B9A\u3057\u305F\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u3059\u3079\u3066\u306E\u30B5\u30D6\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u62E1\u5F35)\u3057\u305F\u3082\u306E\u3067\u3059\u3002\u5404\u306E\u524D\u306B\n'-'\u3092\u6307\u5B9A\u3059\u308B\u3068\u3001\u6307\u5B9A\u3057\u305F1\u3064\u4EE5\u4E0A\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u95A2\u3059\u308B\u30C1\u30A7\u30C3\u30AF\u3092\u7121\u52B9\u306B\u3067\u304D\u307E\u3059\u3002 -javac.opt.doclint.format=\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u306E\u5F62\u5F0F\u3092\u6307\u5B9A\u3057\u307E\u3059 - javac.opt.Xstdout=\u6A19\u6E96\u51FA\u529B\u3092\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3059\u308B javac.opt.X=\u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u51FA\u529B\u3057\u307E\u3059 javac.opt.help=\u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3057\u307E\u3059 +javac.opt.help.lint=-Xlint\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u308B\u30AD\u30FC\u3092\u51FA\u529B\u3057\u307E\u3059 +javac.opt.help.lint.header=-Xlint\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u308B\u30AD\u30FC\u306F\u6B21\u306E\u3068\u304A\u308A\u3067\u3059: javac.opt.print=\u6307\u5B9A\u3057\u305F\u578B\u306E\u30C6\u30AD\u30B9\u30C8\u8868\u793A\u3092\u51FA\u529B\u3059\u308B javac.opt.printRounds=\u6CE8\u91C8\u51E6\u7406\u306E\u5F80\u5FA9\u306B\u3064\u3044\u3066\u306E\u60C5\u5831\u3092\u5370\u5237\u3059\u308B javac.opt.printProcessorInfo=\u30D7\u30ED\u30BB\u30C3\u30B5\u304C\u51E6\u7406\u3092\u4F9D\u983C\u3055\u308C\u308B\u6CE8\u91C8\u306B\u3064\u3044\u3066\u306E\u60C5\u5831\u3092\u5370\u5237\u3059\u308B diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index 3160e9486397de6f092c0746b998d1c0d64ff5a9..0fa374e3f65b4ac5f6fcba1ddae8e2185d55bd62 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -99,7 +99,7 @@ javac.opt.Xlint.all=\u542F\u7528\u6240\u6709\u8B66\u544A javac.opt.Xlint.none=\u7981\u7528\u6240\u6709\u8B66\u544A #L10N: do not localize: -Xlint javac.opt.arg.Xlint=<\u5BC6\u94A5>(,<\u5BC6\u94A5>)* -javac.opt.Xlint.custom=\u8981\u542F\u7528\u6216\u7981\u7528\u7684\u8B66\u544A, \u4F7F\u7528\u9017\u53F7\u5206\u9694\u3002\n \u5728\u5173\u952E\u5B57\u524D\u9762\u52A0\u4E0A '-' \u53EF\u7981\u7528\u6307\u5B9A\u7684\u8B66\u544A\u3002\n \u652F\u6301\u7684\u5173\u952E\u5B57\u5305\u62EC: +javac.opt.Xlint.custom=\u8981\u542F\u7528\u6216\u7981\u7528\u7684\u8B66\u544A\uFF0C\u4F7F\u7528\u9017\u53F7\u5206\u9694\u3002\n\u5728\u5173\u952E\u5B57\u524D\u9762\u52A0\u4E0A '-' \u53EF\u7981\u7528\u6307\u5B9A\u7684\u8B66\u544A\u3002\n\u4F7F\u7528 --help-lint \u53EF\u67E5\u770B\u53D7\u652F\u6301\u7684\u5173\u952E\u5B57\u3002 javac.opt.Xlint.desc.auxiliaryclass=\u6709\u5173\u8F85\u52A9\u7C7B\u5728\u6E90\u6587\u4EF6\u4E2D\u9690\u85CF, \u4F46\u5728\u5176\u4ED6\u6587\u4EF6\u4E2D\u4F7F\u7528\u7684\u8B66\u544A\u3002 javac.opt.Xlint.desc.cast=\u6709\u5173\u4F7F\u7528\u4E86\u4E0D\u5FC5\u8981\u8F6C\u6362\u7684\u8B66\u544A\u3002 @@ -144,10 +144,12 @@ javac.opt.Xlint.desc.requires-automatic=\u6709\u5173\u5728 requires \u5B50\u53E5 javac.opt.Xlint.desc.requires-transitive-automatic=\u6709\u5173 requires \u8FC7\u6E21\u4E2D\u7684\u81EA\u52A8\u6A21\u5757\u7684\u8B66\u544A\u3002 -javac.opt.Xlint.desc.serial=\u6709\u5173\u672A\u63D0\u4F9B\u5E8F\u5217\u7248\u672C ID \u7684\u53EF\u5E8F\u5217\u5316\u7C7B\u7684\u8B66\u544A\u3002\n \u6B64\u5916\u8FD8\u8B66\u544A\u6709\u5173\u53EF\u4E32\u884C\u5316\u5143\u7D20\u5BF9\u975E\u516C\u5171\u6210\u5458\u7684\u8BBF\u95EE\u3002 +javac.opt.Xlint.desc.serial=\u6709\u5173\u6CA1\u6709 serialVersionUID \u5B57\u6BB5\u7684\u53EF\u5E8F\u5217\u5316\u7C7B\u7684\u8B66\u544A\u3002\n \u4EE5\u53CA\u6709\u5173\u53EF\u5E8F\u5217\u5316\u548C\u53EF\u5916\u90E8\u5316\u7684\u7C7B\u548C\u63A5\u53E3\u4E2D\u5176\u4ED6\u53EF\u7591\u58F0\u660E\u7684\u8B66\u544A\u3002 javac.opt.Xlint.desc.static=\u6709\u5173\u4F7F\u7528\u5B9E\u4F8B\u6765\u8BBF\u95EE\u9759\u6001\u6210\u5458\u7684\u8B66\u544A\u3002 +javac.opt.Xlint.desc.strictfp=\u6709\u5173\u4E0D\u5FC5\u8981\u5730\u4F7F\u7528\u4E86 strictfp \u4FEE\u9970\u7B26\u7684\u8B66\u544A\u3002 + javac.opt.Xlint.desc.text-blocks=\u6709\u5173\u6587\u672C\u5757\u7F29\u8FDB\u4E2D\u7684\u7A7A\u683C\u5B57\u7B26\u4E0D\u4E00\u81F4\u7684\u8B66\u544A\u3002 javac.opt.Xlint.desc.try=\u6709\u5173\u4E0E\u4F7F\u7528 try \u5757 (\u4F8B\u5982 try-with-resources) \u76F8\u5173\u7684\u95EE\u9898\u7684\u8B66\u544A\u3002 @@ -172,11 +174,11 @@ javac.opt.Xdoclint.package.args = [-]<\u7A0B\u5E8F\u5305>(,[-]<\u7A0B\u5E8F\u530 javac.opt.Xdoclint.package.desc=\u5728\u7279\u5B9A\u7684\u7A0B\u5E8F\u5305\u4E2D\u542F\u7528\u6216\u7981\u7528\u68C0\u67E5\u3002\u6BCF\u4E2A <\u7A0B\u5E8F\u5305> \u662F\n\u7A0B\u5E8F\u5305\u7684\u9650\u5B9A\u540D\u79F0, \u6216\u7A0B\u5E8F\u5305\u540D\u79F0\u524D\u7F00\u540E\u8DDF '.*', \n\u5B83\u6269\u5C55\u5230\u7ED9\u5B9A\u7A0B\u5E8F\u5305\u7684\u6240\u6709\u5B50\u7A0B\u5E8F\u5305\u3002\u5728\u6BCF\u4E2A <\u7A0B\u5E8F\u5305>\n\u524D\u9762\u52A0\u4E0A '-' \u53EF\u4EE5\u4E3A\u6307\u5B9A\u7A0B\u5E8F\u5305\u7981\u7528\u68C0\u67E5\u3002 -javac.opt.doclint.format=\u6307\u5B9A\u6587\u6863\u6CE8\u91CA\u7684\u683C\u5F0F - javac.opt.Xstdout=\u91CD\u5B9A\u5411\u6807\u51C6\u8F93\u51FA javac.opt.X=\u8F93\u51FA\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9 javac.opt.help=\u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F +javac.opt.help.lint=\u8F93\u51FA -Xlint \u652F\u6301\u7684\u5173\u952E\u5B57 +javac.opt.help.lint.header=-Xlint \u652F\u6301\u7684\u5173\u952E\u5B57\u5305\u62EC\uFF1A javac.opt.print=\u8F93\u51FA\u6307\u5B9A\u7C7B\u578B\u7684\u6587\u672C\u8868\u793A javac.opt.printRounds=\u8F93\u51FA\u6709\u5173\u6CE8\u91CA\u5904\u7406\u5FAA\u73AF\u7684\u4FE1\u606F javac.opt.printProcessorInfo=\u8F93\u51FA\u6709\u5173\u8BF7\u6C42\u5904\u7406\u7A0B\u5E8F\u5904\u7406\u54EA\u4E9B\u6CE8\u91CA\u7684\u4FE1\u606F diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..a5796a168dfee0905f7634e5ffbdcfa2d1ab7bae --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties @@ -0,0 +1,117 @@ +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +# Messages in this file which use "placeholders" for values (e.g. {0}, {1}) +# are preceded by a stylized comment describing the type of the corresponding +# values. +# The simple types currently in use are: +# +# annotation annotation compound +# boolean true or false +# diagnostic a sub-message; see compiler.misc.* +# fragment similar to 'message segment', but with more specific type +# modifier a Java modifier; e.g. public, private, protected +# file a file URL +# file object a file URL - similar to 'file' but typically used for source/class files, hence more specific +# flag a Flags.Flag instance +# name a name, typically a Java identifier +# number an integer +# option name the name of a command line option +# source version a source version number, such as 1.5, 1.6, 1.7 +# string a general string +# symbol the name of a declared type +# symbol kind the kind of a symbol (i.e. method, variable) +# kind name an informative description of the kind of a declaration; see compiler.misc.kindname.* +# token the name of a non-terminal in source code; see compiler.misc.token.* +# type a Java type; e.g. int, X, X +# object a Java object (unspecified) +# unused the value is not used in this message +# +# The following compound types are also used: +# +# collection of X a comma-separated collection of items; e.g. collection of type +# list of X a comma-separated list of items; e.g. list of type +# set of X a comma-separated set of items; e.g. set of modifier +# +# These may be composed: +# +# list of type or message segment +# +# The following type aliases are supported: +# +# message segment --> diagnostic or fragment +# file name --> file, path or file object +# +# Custom comments are supported in parenthesis i.e. +# +# number (classfile major version) +# +# These comments are used internally in order to generate an enum-like class declaration containing +# a method/field for each of the diagnostic keys listed here. Those methods/fields can then be used +# by javac code to build diagnostics in a type-safe fashion. +# +# In addition, these comments are verified by the jtreg test test/tools/javac/diags/MessageInfo, +# using info derived from the collected set of examples in test/tools/javac/diags/examples. +# MessageInfo can also be run as a standalone utility providing more facilities +# for manipulating this file. For more details, see MessageInfo.java. + +## All errors are preceded by this string. +launcher.error=Fehler: + +launcher.err.no.args=kein Pfad f\u00FCr Quelldatei + +# 0: string +launcher.err.invalid.filename=ung\u00FCltiger Pfad f\u00FCr Quelldatei: {0} + +# 0: path +launcher.err.file.not.found=Quelldatei nicht gefunden: {0} + +launcher.err.compilation.failed=Kompilierung nicht erfolgreich + +launcher.err.no.class=keine Klasse deklariert in Quelldatei + +launcher.err.main.not.public.static=Methode "main" ist nicht als "public static" deklariert + +launcher.err.main.not.void=Methode "main" ist nicht mit R\u00FCckgabetyp "void" deklariert + +# 0: string +launcher.err.cant.find.class=Klasse nicht gefunden: {0} + +# 0: string +launcher.err.cant.find.main.method=Methode "main(String[])" nicht gefunden in Klasse: {0} + +# 0: string +launcher.err.cant.access.main.method=kein Zugriff auf Methode "main" in Klasse: {0} + +# 0: path, 1: object +launcher.err.cant.read.file=Fehler beim Lesen von Quelldatei {0}: {1} + +# 0: string +launcher.err.no.value.for.option=kein Wert angegeben f\u00FCr Option: {0} + +# 0: string +launcher.err.invalid.value.for.source=ung\u00FCltiger Wert f\u00FCr Option --source: {0} + +launcher.err.enable.preview.requires.source=--enable-preview muss mit --source verwendet werden diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java index acccd4d574cca6d84c64def724d947c956190912..bdfef06fd7c53143e0c02a38eeca949038371251 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.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 @@ -194,9 +194,7 @@ public class Pretty extends JCTree.Visitor { tree.accept(this); } } catch (UncheckedIOException ex) { - IOException e = new IOException(ex.getMessage()); - e.initCause(ex); - throw e; + throw new IOException(ex.getMessage(), ex); } finally { this.prec = prevPrec; } diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..fac9b7e1e2e874df697254e6fc49542d92167883 --- /dev/null +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties @@ -0,0 +1,31 @@ +# +# Copyright (c) 2010, 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. 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. +# + +NotSerializable=Klasse {0} ist nicht serialisierbar. +ClassNotFound=Klasse {0} nicht gefunden. +error.parsing.classpath=Fehler beim Parsen von Classpath {0}. +error.missing.classpath=Fehlendes Argument bei Option -classpath +invalid.flag=Ung\u00FCltiges Flag {0}. +usage=Verwendung: serialver [-classpath classpath] [classname...] diff --git a/make/data/symbols/README b/src/jdk.compiler/share/data/symbols/README similarity index 100% rename from make/data/symbols/README rename to src/jdk.compiler/share/data/symbols/README diff --git a/make/data/symbols/include.list b/src/jdk.compiler/share/data/symbols/include.list similarity index 100% rename from make/data/symbols/include.list rename to src/jdk.compiler/share/data/symbols/include.list diff --git a/make/data/symbols/java.activation-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.activation-8.sym.txt similarity index 100% rename from make/data/symbols/java.activation-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.activation-8.sym.txt diff --git a/make/data/symbols/java.activation-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.activation-9.sym.txt similarity index 100% rename from make/data/symbols/java.activation-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.activation-9.sym.txt diff --git a/make/data/symbols/java.activation-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.activation-A.sym.txt similarity index 100% rename from make/data/symbols/java.activation-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.activation-A.sym.txt diff --git a/make/data/symbols/java.activation-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.activation-B.sym.txt similarity index 100% rename from make/data/symbols/java.activation-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.activation-B.sym.txt diff --git a/make/data/symbols/java.base-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-7.sym.txt similarity index 100% rename from make/data/symbols/java.base-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-7.sym.txt diff --git a/make/data/symbols/java.base-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-8.sym.txt similarity index 100% rename from make/data/symbols/java.base-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-8.sym.txt diff --git a/make/data/symbols/java.base-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-9.sym.txt similarity index 100% rename from make/data/symbols/java.base-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-9.sym.txt diff --git a/make/data/symbols/java.base-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-A.sym.txt similarity index 100% rename from make/data/symbols/java.base-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-A.sym.txt diff --git a/make/data/symbols/java.base-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-B.sym.txt similarity index 100% rename from make/data/symbols/java.base-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-B.sym.txt diff --git a/make/data/symbols/java.base-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-C.sym.txt similarity index 100% rename from make/data/symbols/java.base-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-C.sym.txt diff --git a/make/data/symbols/java.base-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-D.sym.txt similarity index 100% rename from make/data/symbols/java.base-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-D.sym.txt diff --git a/make/data/symbols/java.base-E.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-E.sym.txt similarity index 100% rename from make/data/symbols/java.base-E.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-E.sym.txt diff --git a/make/data/symbols/java.base-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-F.sym.txt similarity index 100% rename from make/data/symbols/java.base-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-F.sym.txt diff --git a/make/data/symbols/java.base-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-G.sym.txt similarity index 100% rename from make/data/symbols/java.base-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-G.sym.txt diff --git a/make/data/symbols/java.base-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-H.sym.txt similarity index 100% rename from make/data/symbols/java.base-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-H.sym.txt diff --git a/make/data/symbols/java.base-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-I.sym.txt similarity index 100% rename from make/data/symbols/java.base-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.base-I.sym.txt diff --git a/make/data/symbols/java.compiler-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-7.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-7.sym.txt diff --git a/make/data/symbols/java.compiler-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-8.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-8.sym.txt diff --git a/make/data/symbols/java.compiler-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-9.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-9.sym.txt diff --git a/make/data/symbols/java.compiler-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-A.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-A.sym.txt diff --git a/make/data/symbols/java.compiler-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-B.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-B.sym.txt diff --git a/make/data/symbols/java.compiler-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-C.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-C.sym.txt diff --git a/make/data/symbols/java.compiler-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-D.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-D.sym.txt diff --git a/make/data/symbols/java.compiler-E.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-E.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-E.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-E.sym.txt diff --git a/make/data/symbols/java.compiler-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-F.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-F.sym.txt diff --git a/make/data/symbols/java.compiler-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-G.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-G.sym.txt diff --git a/make/data/symbols/java.compiler-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-H.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-H.sym.txt diff --git a/make/data/symbols/java.compiler-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-I.sym.txt similarity index 100% rename from make/data/symbols/java.compiler-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.compiler-I.sym.txt diff --git a/make/data/symbols/java.corba-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.corba-8.sym.txt similarity index 100% rename from make/data/symbols/java.corba-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.corba-8.sym.txt diff --git a/make/data/symbols/java.corba-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.corba-9.sym.txt similarity index 100% rename from make/data/symbols/java.corba-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.corba-9.sym.txt diff --git a/make/data/symbols/java.corba-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.corba-A.sym.txt similarity index 100% rename from make/data/symbols/java.corba-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.corba-A.sym.txt diff --git a/make/data/symbols/java.corba-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.corba-B.sym.txt similarity index 100% rename from make/data/symbols/java.corba-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.corba-B.sym.txt diff --git a/make/data/symbols/java.datatransfer-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-7.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-7.sym.txt diff --git a/make/data/symbols/java.datatransfer-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-8.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-8.sym.txt diff --git a/make/data/symbols/java.datatransfer-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-9.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-9.sym.txt diff --git a/make/data/symbols/java.datatransfer-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-A.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-A.sym.txt diff --git a/make/data/symbols/java.datatransfer-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-B.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-B.sym.txt diff --git a/make/data/symbols/java.datatransfer-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-G.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-G.sym.txt diff --git a/make/data/symbols/java.datatransfer-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-H.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-H.sym.txt diff --git a/make/data/symbols/java.datatransfer-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-I.sym.txt similarity index 100% rename from make/data/symbols/java.datatransfer-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.datatransfer-I.sym.txt diff --git a/make/data/symbols/java.desktop-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-7.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-7.sym.txt diff --git a/make/data/symbols/java.desktop-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt diff --git a/make/data/symbols/java.desktop-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt diff --git a/make/data/symbols/java.desktop-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-A.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-A.sym.txt diff --git a/make/data/symbols/java.desktop-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-B.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-B.sym.txt diff --git a/make/data/symbols/java.desktop-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-C.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-C.sym.txt diff --git a/make/data/symbols/java.desktop-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-D.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-D.sym.txt diff --git a/make/data/symbols/java.desktop-E.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-E.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-E.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-E.sym.txt diff --git a/make/data/symbols/java.desktop-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-F.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-F.sym.txt diff --git a/make/data/symbols/java.desktop-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-G.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-G.sym.txt diff --git a/make/data/symbols/java.desktop-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-H.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-H.sym.txt diff --git a/make/data/symbols/java.desktop-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-I.sym.txt similarity index 100% rename from make/data/symbols/java.desktop-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.desktop-I.sym.txt diff --git a/make/data/symbols/java.instrument-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-8.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-8.sym.txt diff --git a/make/data/symbols/java.instrument-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-9.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-9.sym.txt diff --git a/make/data/symbols/java.instrument-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-A.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-A.sym.txt diff --git a/make/data/symbols/java.instrument-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-B.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-B.sym.txt diff --git a/make/data/symbols/java.instrument-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-G.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-G.sym.txt diff --git a/make/data/symbols/java.instrument-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-H.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-H.sym.txt diff --git a/make/data/symbols/java.instrument-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-I.sym.txt similarity index 100% rename from make/data/symbols/java.instrument-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.instrument-I.sym.txt diff --git a/make/data/symbols/java.logging-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-7.sym.txt similarity index 100% rename from make/data/symbols/java.logging-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-7.sym.txt diff --git a/make/data/symbols/java.logging-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-8.sym.txt similarity index 100% rename from make/data/symbols/java.logging-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-8.sym.txt diff --git a/make/data/symbols/java.logging-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-9.sym.txt similarity index 100% rename from make/data/symbols/java.logging-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-9.sym.txt diff --git a/make/data/symbols/java.logging-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-A.sym.txt similarity index 100% rename from make/data/symbols/java.logging-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-A.sym.txt diff --git a/make/data/symbols/java.logging-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-B.sym.txt similarity index 100% rename from make/data/symbols/java.logging-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-B.sym.txt diff --git a/make/data/symbols/java.logging-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-G.sym.txt similarity index 100% rename from make/data/symbols/java.logging-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-G.sym.txt diff --git a/make/data/symbols/java.logging-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-H.sym.txt similarity index 100% rename from make/data/symbols/java.logging-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-H.sym.txt diff --git a/make/data/symbols/java.logging-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-I.sym.txt similarity index 100% rename from make/data/symbols/java.logging-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.logging-I.sym.txt diff --git a/make/data/symbols/java.management-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-7.sym.txt similarity index 100% rename from make/data/symbols/java.management-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-7.sym.txt diff --git a/make/data/symbols/java.management-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-8.sym.txt similarity index 100% rename from make/data/symbols/java.management-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-8.sym.txt diff --git a/make/data/symbols/java.management-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-9.sym.txt similarity index 100% rename from make/data/symbols/java.management-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-9.sym.txt diff --git a/make/data/symbols/java.management-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-A.sym.txt similarity index 100% rename from make/data/symbols/java.management-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-A.sym.txt diff --git a/make/data/symbols/java.management-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-B.sym.txt similarity index 100% rename from make/data/symbols/java.management-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-B.sym.txt diff --git a/make/data/symbols/java.management-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-D.sym.txt similarity index 100% rename from make/data/symbols/java.management-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-D.sym.txt diff --git a/make/data/symbols/java.management-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-G.sym.txt similarity index 100% rename from make/data/symbols/java.management-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-G.sym.txt diff --git a/make/data/symbols/java.management-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-H.sym.txt similarity index 100% rename from make/data/symbols/java.management-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-H.sym.txt diff --git a/make/data/symbols/java.management-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-I.sym.txt similarity index 100% rename from make/data/symbols/java.management-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management-I.sym.txt diff --git a/make/data/symbols/java.management.rmi-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-8.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-8.sym.txt diff --git a/make/data/symbols/java.management.rmi-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-9.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-9.sym.txt diff --git a/make/data/symbols/java.management.rmi-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-A.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-A.sym.txt diff --git a/make/data/symbols/java.management.rmi-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-B.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-B.sym.txt diff --git a/make/data/symbols/java.management.rmi-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-D.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-D.sym.txt diff --git a/make/data/symbols/java.management.rmi-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-F.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-F.sym.txt diff --git a/make/data/symbols/java.management.rmi-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-G.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-G.sym.txt diff --git a/make/data/symbols/java.management.rmi-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-H.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-H.sym.txt diff --git a/make/data/symbols/java.management.rmi-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-I.sym.txt similarity index 100% rename from make/data/symbols/java.management.rmi-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.management.rmi-I.sym.txt diff --git a/make/data/symbols/java.naming-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-7.sym.txt similarity index 100% rename from make/data/symbols/java.naming-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-7.sym.txt diff --git a/make/data/symbols/java.naming-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-8.sym.txt similarity index 100% rename from make/data/symbols/java.naming-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-8.sym.txt diff --git a/make/data/symbols/java.naming-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-9.sym.txt similarity index 100% rename from make/data/symbols/java.naming-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-9.sym.txt diff --git a/make/data/symbols/java.naming-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-A.sym.txt similarity index 100% rename from make/data/symbols/java.naming-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-A.sym.txt diff --git a/make/data/symbols/java.naming-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-B.sym.txt similarity index 100% rename from make/data/symbols/java.naming-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-B.sym.txt diff --git a/make/data/symbols/java.naming-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-C.sym.txt similarity index 100% rename from make/data/symbols/java.naming-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-C.sym.txt diff --git a/make/data/symbols/java.naming-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-F.sym.txt similarity index 100% rename from make/data/symbols/java.naming-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-F.sym.txt diff --git a/make/data/symbols/java.naming-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-G.sym.txt similarity index 100% rename from make/data/symbols/java.naming-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-G.sym.txt diff --git a/make/data/symbols/java.naming-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-H.sym.txt similarity index 100% rename from make/data/symbols/java.naming-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-H.sym.txt diff --git a/make/data/symbols/java.naming-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-I.sym.txt similarity index 100% rename from make/data/symbols/java.naming-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.naming-I.sym.txt diff --git a/make/data/symbols/java.net.http-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.net.http-B.sym.txt similarity index 100% rename from make/data/symbols/java.net.http-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.net.http-B.sym.txt diff --git a/make/data/symbols/java.net.http-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.net.http-D.sym.txt similarity index 100% rename from make/data/symbols/java.net.http-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.net.http-D.sym.txt diff --git a/make/data/symbols/java.net.http-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.net.http-G.sym.txt similarity index 100% rename from make/data/symbols/java.net.http-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.net.http-G.sym.txt diff --git a/make/data/symbols/java.net.http-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.net.http-I.sym.txt similarity index 100% rename from make/data/symbols/java.net.http-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.net.http-I.sym.txt diff --git a/make/data/symbols/java.prefs-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.prefs-7.sym.txt similarity index 100% rename from make/data/symbols/java.prefs-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.prefs-7.sym.txt diff --git a/make/data/symbols/java.prefs-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.prefs-8.sym.txt similarity index 100% rename from make/data/symbols/java.prefs-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.prefs-8.sym.txt diff --git a/make/data/symbols/java.prefs-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.prefs-9.sym.txt similarity index 100% rename from make/data/symbols/java.prefs-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.prefs-9.sym.txt diff --git a/make/data/symbols/java.prefs-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.prefs-A.sym.txt similarity index 100% rename from make/data/symbols/java.prefs-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.prefs-A.sym.txt diff --git a/make/data/symbols/java.prefs-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.prefs-B.sym.txt similarity index 100% rename from make/data/symbols/java.prefs-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.prefs-B.sym.txt diff --git a/make/data/symbols/java.rmi-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-7.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-7.sym.txt diff --git a/make/data/symbols/java.rmi-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-8.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-8.sym.txt diff --git a/make/data/symbols/java.rmi-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-9.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-9.sym.txt diff --git a/make/data/symbols/java.rmi-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-A.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-A.sym.txt diff --git a/make/data/symbols/java.rmi-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-B.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-B.sym.txt diff --git a/make/data/symbols/java.rmi-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-C.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-C.sym.txt diff --git a/make/data/symbols/java.rmi-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-F.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-F.sym.txt diff --git a/make/data/symbols/java.rmi-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-G.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-G.sym.txt diff --git a/make/data/symbols/java.rmi-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-H.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-H.sym.txt diff --git a/make/data/symbols/java.rmi-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-I.sym.txt similarity index 100% rename from make/data/symbols/java.rmi-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.rmi-I.sym.txt diff --git a/make/data/symbols/java.scripting-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-7.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-7.sym.txt diff --git a/make/data/symbols/java.scripting-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-8.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-8.sym.txt diff --git a/make/data/symbols/java.scripting-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-9.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-9.sym.txt diff --git a/make/data/symbols/java.scripting-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-A.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-A.sym.txt diff --git a/make/data/symbols/java.scripting-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-B.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-B.sym.txt diff --git a/make/data/symbols/java.scripting-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-G.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-G.sym.txt diff --git a/make/data/symbols/java.scripting-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-H.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-H.sym.txt diff --git a/make/data/symbols/java.scripting-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-I.sym.txt similarity index 100% rename from make/data/symbols/java.scripting-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.scripting-I.sym.txt diff --git a/make/data/symbols/java.se-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.se-9.sym.txt similarity index 100% rename from make/data/symbols/java.se-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se-9.sym.txt diff --git a/make/data/symbols/java.se-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.se-A.sym.txt similarity index 100% rename from make/data/symbols/java.se-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se-A.sym.txt diff --git a/make/data/symbols/java.se-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.se-B.sym.txt similarity index 100% rename from make/data/symbols/java.se-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se-B.sym.txt diff --git a/make/data/symbols/java.se.ee-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.se.ee-9.sym.txt similarity index 100% rename from make/data/symbols/java.se.ee-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se.ee-9.sym.txt diff --git a/make/data/symbols/java.se.ee-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.se.ee-A.sym.txt similarity index 100% rename from make/data/symbols/java.se.ee-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se.ee-A.sym.txt diff --git a/make/data/symbols/java.se.ee-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.se.ee-B.sym.txt similarity index 100% rename from make/data/symbols/java.se.ee-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.se.ee-B.sym.txt diff --git a/make/data/symbols/java.security.jgss-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-7.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-7.sym.txt diff --git a/make/data/symbols/java.security.jgss-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-8.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-8.sym.txt diff --git a/make/data/symbols/java.security.jgss-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-9.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-9.sym.txt diff --git a/make/data/symbols/java.security.jgss-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-A.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-A.sym.txt diff --git a/make/data/symbols/java.security.jgss-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-B.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-B.sym.txt diff --git a/make/data/symbols/java.security.jgss-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-D.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-D.sym.txt diff --git a/make/data/symbols/java.security.jgss-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-G.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-G.sym.txt diff --git a/make/data/symbols/java.security.jgss-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-H.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-H.sym.txt diff --git a/make/data/symbols/java.security.jgss-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-I.sym.txt similarity index 100% rename from make/data/symbols/java.security.jgss-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.jgss-I.sym.txt diff --git a/make/data/symbols/java.security.sasl-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-7.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-7.sym.txt diff --git a/make/data/symbols/java.security.sasl-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-8.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-8.sym.txt diff --git a/make/data/symbols/java.security.sasl-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-9.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-9.sym.txt diff --git a/make/data/symbols/java.security.sasl-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-A.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-A.sym.txt diff --git a/make/data/symbols/java.security.sasl-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-B.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-B.sym.txt diff --git a/make/data/symbols/java.security.sasl-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-G.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-G.sym.txt diff --git a/make/data/symbols/java.security.sasl-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-H.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-H.sym.txt diff --git a/make/data/symbols/java.security.sasl-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-I.sym.txt similarity index 100% rename from make/data/symbols/java.security.sasl-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.security.sasl-I.sym.txt diff --git a/make/data/symbols/java.smartcardio-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-9.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-9.sym.txt diff --git a/make/data/symbols/java.smartcardio-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-A.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-A.sym.txt diff --git a/make/data/symbols/java.smartcardio-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-B.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-B.sym.txt diff --git a/make/data/symbols/java.smartcardio-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-G.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-G.sym.txt diff --git a/make/data/symbols/java.smartcardio-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-H.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-H.sym.txt diff --git a/make/data/symbols/java.smartcardio-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-I.sym.txt similarity index 100% rename from make/data/symbols/java.smartcardio-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.smartcardio-I.sym.txt diff --git a/make/data/symbols/java.sql-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-7.sym.txt similarity index 100% rename from make/data/symbols/java.sql-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-7.sym.txt diff --git a/make/data/symbols/java.sql-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-8.sym.txt similarity index 100% rename from make/data/symbols/java.sql-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-8.sym.txt diff --git a/make/data/symbols/java.sql-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-9.sym.txt similarity index 100% rename from make/data/symbols/java.sql-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-9.sym.txt diff --git a/make/data/symbols/java.sql-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-A.sym.txt similarity index 100% rename from make/data/symbols/java.sql-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-A.sym.txt diff --git a/make/data/symbols/java.sql-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-B.sym.txt similarity index 100% rename from make/data/symbols/java.sql-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-B.sym.txt diff --git a/make/data/symbols/java.sql-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-G.sym.txt similarity index 100% rename from make/data/symbols/java.sql-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-G.sym.txt diff --git a/make/data/symbols/java.sql-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-H.sym.txt similarity index 100% rename from make/data/symbols/java.sql-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-H.sym.txt diff --git a/make/data/symbols/java.sql-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-I.sym.txt similarity index 100% rename from make/data/symbols/java.sql-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql-I.sym.txt diff --git a/make/data/symbols/java.sql.rowset-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-7.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-7.sym.txt diff --git a/make/data/symbols/java.sql.rowset-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-8.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-8.sym.txt diff --git a/make/data/symbols/java.sql.rowset-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-9.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-9.sym.txt diff --git a/make/data/symbols/java.sql.rowset-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-A.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-A.sym.txt diff --git a/make/data/symbols/java.sql.rowset-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-B.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-B.sym.txt diff --git a/make/data/symbols/java.sql.rowset-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-G.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-G.sym.txt diff --git a/make/data/symbols/java.sql.rowset-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-H.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-H.sym.txt diff --git a/make/data/symbols/java.sql.rowset-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-I.sym.txt similarity index 100% rename from make/data/symbols/java.sql.rowset-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.sql.rowset-I.sym.txt diff --git a/make/data/symbols/java.transaction-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.transaction-8.sym.txt similarity index 100% rename from make/data/symbols/java.transaction-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.transaction-8.sym.txt diff --git a/make/data/symbols/java.transaction-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.transaction-9.sym.txt similarity index 100% rename from make/data/symbols/java.transaction-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.transaction-9.sym.txt diff --git a/make/data/symbols/java.transaction-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.transaction-A.sym.txt similarity index 100% rename from make/data/symbols/java.transaction-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.transaction-A.sym.txt diff --git a/make/data/symbols/java.transaction-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.transaction-B.sym.txt similarity index 100% rename from make/data/symbols/java.transaction-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.transaction-B.sym.txt diff --git a/make/data/symbols/java.transaction.xa-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.transaction.xa-B.sym.txt similarity index 100% rename from make/data/symbols/java.transaction.xa-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.transaction.xa-B.sym.txt diff --git a/make/data/symbols/java.xml-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-7.sym.txt similarity index 100% rename from make/data/symbols/java.xml-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-7.sym.txt diff --git a/make/data/symbols/java.xml-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-8.sym.txt similarity index 100% rename from make/data/symbols/java.xml-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-8.sym.txt diff --git a/make/data/symbols/java.xml-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-9.sym.txt similarity index 100% rename from make/data/symbols/java.xml-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-9.sym.txt diff --git a/make/data/symbols/java.xml-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-A.sym.txt similarity index 100% rename from make/data/symbols/java.xml-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-A.sym.txt diff --git a/make/data/symbols/java.xml-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-B.sym.txt similarity index 100% rename from make/data/symbols/java.xml-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-B.sym.txt diff --git a/make/data/symbols/java.xml-C.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-C.sym.txt similarity index 100% rename from make/data/symbols/java.xml-C.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-C.sym.txt diff --git a/make/data/symbols/java.xml-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-D.sym.txt similarity index 100% rename from make/data/symbols/java.xml-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-D.sym.txt diff --git a/make/data/symbols/java.xml-E.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-E.sym.txt similarity index 100% rename from make/data/symbols/java.xml-E.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-E.sym.txt diff --git a/make/data/symbols/java.xml-F.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-F.sym.txt similarity index 100% rename from make/data/symbols/java.xml-F.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-F.sym.txt diff --git a/make/data/symbols/java.xml-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-G.sym.txt similarity index 100% rename from make/data/symbols/java.xml-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-G.sym.txt diff --git a/make/data/symbols/java.xml-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-H.sym.txt similarity index 100% rename from make/data/symbols/java.xml-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-H.sym.txt diff --git a/make/data/symbols/java.xml-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-I.sym.txt similarity index 100% rename from make/data/symbols/java.xml-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml-I.sym.txt diff --git a/make/data/symbols/java.xml.bind-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-7.sym.txt similarity index 100% rename from make/data/symbols/java.xml.bind-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.bind-7.sym.txt diff --git a/make/data/symbols/java.xml.bind-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-8.sym.txt similarity index 100% rename from make/data/symbols/java.xml.bind-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.bind-8.sym.txt diff --git a/make/data/symbols/java.xml.bind-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt similarity index 100% rename from make/data/symbols/java.xml.bind-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt diff --git a/make/data/symbols/java.xml.bind-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-A.sym.txt similarity index 100% rename from make/data/symbols/java.xml.bind-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.bind-A.sym.txt diff --git a/make/data/symbols/java.xml.bind-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-B.sym.txt similarity index 100% rename from make/data/symbols/java.xml.bind-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.bind-B.sym.txt diff --git a/make/data/symbols/java.xml.crypto-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-8.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-8.sym.txt diff --git a/make/data/symbols/java.xml.crypto-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-9.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-9.sym.txt diff --git a/make/data/symbols/java.xml.crypto-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-A.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-A.sym.txt diff --git a/make/data/symbols/java.xml.crypto-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-B.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-B.sym.txt diff --git a/make/data/symbols/java.xml.crypto-D.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-D.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-D.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-D.sym.txt diff --git a/make/data/symbols/java.xml.crypto-G.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-G.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-G.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-G.sym.txt diff --git a/make/data/symbols/java.xml.crypto-H.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-H.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-H.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-H.sym.txt diff --git a/make/data/symbols/java.xml.crypto-I.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-I.sym.txt similarity index 100% rename from make/data/symbols/java.xml.crypto-I.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.crypto-I.sym.txt diff --git a/make/data/symbols/java.xml.ws-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws-8.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws-8.sym.txt diff --git a/make/data/symbols/java.xml.ws-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws-9.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws-9.sym.txt diff --git a/make/data/symbols/java.xml.ws-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws-A.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws-A.sym.txt diff --git a/make/data/symbols/java.xml.ws-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws-B.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws-B.sym.txt diff --git a/make/data/symbols/java.xml.ws.annotation-7.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-7.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws.annotation-7.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-7.sym.txt diff --git a/make/data/symbols/java.xml.ws.annotation-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-8.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws.annotation-8.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-8.sym.txt diff --git a/make/data/symbols/java.xml.ws.annotation-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-9.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws.annotation-9.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-9.sym.txt diff --git a/make/data/symbols/java.xml.ws.annotation-A.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-A.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws.annotation-A.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-A.sym.txt diff --git a/make/data/symbols/java.xml.ws.annotation-B.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-B.sym.txt similarity index 100% rename from make/data/symbols/java.xml.ws.annotation-B.sym.txt rename to src/jdk.compiler/share/data/symbols/java.xml.ws.annotation-B.sym.txt diff --git a/make/data/symbols/jdk.accessibility-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-9.sym.txt diff --git a/make/data/symbols/jdk.accessibility-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-A.sym.txt diff --git a/make/data/symbols/jdk.accessibility-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-B.sym.txt diff --git a/make/data/symbols/jdk.accessibility-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-G.sym.txt diff --git a/make/data/symbols/jdk.accessibility-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-H.sym.txt diff --git a/make/data/symbols/jdk.accessibility-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.accessibility-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.accessibility-I.sym.txt diff --git a/make/data/symbols/jdk.attach-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-9.sym.txt diff --git a/make/data/symbols/jdk.attach-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-A.sym.txt diff --git a/make/data/symbols/jdk.attach-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-B.sym.txt diff --git a/make/data/symbols/jdk.attach-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-G.sym.txt diff --git a/make/data/symbols/jdk.attach-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-H.sym.txt diff --git a/make/data/symbols/jdk.attach-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.attach-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.attach-I.sym.txt diff --git a/make/data/symbols/jdk.charsets-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.charsets-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.charsets-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.charsets-9.sym.txt diff --git a/make/data/symbols/jdk.charsets-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.charsets-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.charsets-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.charsets-A.sym.txt diff --git a/make/data/symbols/jdk.charsets-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.charsets-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.charsets-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.charsets-B.sym.txt diff --git a/make/data/symbols/jdk.compiler-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-9.sym.txt diff --git a/make/data/symbols/jdk.compiler-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-A.sym.txt diff --git a/make/data/symbols/jdk.compiler-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-B.sym.txt diff --git a/make/data/symbols/jdk.compiler-C.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-C.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-C.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-C.sym.txt diff --git a/make/data/symbols/jdk.compiler-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-D.sym.txt diff --git a/make/data/symbols/jdk.compiler-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-E.sym.txt diff --git a/make/data/symbols/jdk.compiler-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-F.sym.txt diff --git a/make/data/symbols/jdk.compiler-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-G.sym.txt diff --git a/make/data/symbols/jdk.compiler-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-H.sym.txt diff --git a/make/data/symbols/jdk.compiler-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.compiler-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.compiler-I.sym.txt diff --git a/make/data/symbols/jdk.crypto.cryptoki-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.cryptoki-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-9.sym.txt diff --git a/make/data/symbols/jdk.crypto.cryptoki-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.cryptoki-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-A.sym.txt diff --git a/make/data/symbols/jdk.crypto.cryptoki-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.cryptoki-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.cryptoki-B.sym.txt diff --git a/make/data/symbols/jdk.crypto.ec-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.ec-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.ec-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.ec-9.sym.txt diff --git a/make/data/symbols/jdk.crypto.ec-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.ec-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.ec-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.ec-A.sym.txt diff --git a/make/data/symbols/jdk.crypto.ec-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.crypto.ec-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.crypto.ec-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.crypto.ec-B.sym.txt diff --git a/make/data/symbols/jdk.dynalink-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-9.sym.txt diff --git a/make/data/symbols/jdk.dynalink-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-A.sym.txt diff --git a/make/data/symbols/jdk.dynalink-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-B.sym.txt diff --git a/make/data/symbols/jdk.dynalink-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-G.sym.txt diff --git a/make/data/symbols/jdk.dynalink-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-H.sym.txt diff --git a/make/data/symbols/jdk.dynalink-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.dynalink-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.dynalink-I.sym.txt diff --git a/make/data/symbols/jdk.editpad-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.editpad-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.editpad-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.editpad-9.sym.txt diff --git a/make/data/symbols/jdk.editpad-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.editpad-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.editpad-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.editpad-A.sym.txt diff --git a/make/data/symbols/jdk.editpad-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.editpad-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.editpad-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.editpad-B.sym.txt diff --git a/make/data/symbols/jdk.hotspot.agent-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.hotspot.agent-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-9.sym.txt diff --git a/make/data/symbols/jdk.hotspot.agent-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.hotspot.agent-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-A.sym.txt diff --git a/make/data/symbols/jdk.hotspot.agent-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.hotspot.agent-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.hotspot.agent-B.sym.txt diff --git a/make/data/symbols/jdk.httpserver-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-7.sym.txt diff --git a/make/data/symbols/jdk.httpserver-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-8.sym.txt diff --git a/make/data/symbols/jdk.httpserver-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-9.sym.txt diff --git a/make/data/symbols/jdk.httpserver-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-A.sym.txt diff --git a/make/data/symbols/jdk.httpserver-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-B.sym.txt diff --git a/make/data/symbols/jdk.httpserver-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-D.sym.txt diff --git a/make/data/symbols/jdk.httpserver-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-E.sym.txt diff --git a/make/data/symbols/jdk.httpserver-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-G.sym.txt diff --git a/make/data/symbols/jdk.httpserver-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-H.sym.txt diff --git a/make/data/symbols/jdk.httpserver-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.httpserver-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.httpserver-I.sym.txt diff --git a/make/data/symbols/jdk.incubator.foreign-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.foreign-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-E.sym.txt diff --git a/make/data/symbols/jdk.incubator.foreign-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.foreign-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-F.sym.txt diff --git a/make/data/symbols/jdk.incubator.foreign-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.foreign-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-G.sym.txt diff --git a/make/data/symbols/jdk.incubator.foreign-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.foreign-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-H.sym.txt diff --git a/make/data/symbols/jdk.incubator.foreign-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.foreign-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-I.sym.txt diff --git a/make/data/symbols/jdk.incubator.httpclient-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.httpclient-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-9.sym.txt diff --git a/make/data/symbols/jdk.incubator.httpclient-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.httpclient-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-A.sym.txt diff --git a/make/data/symbols/jdk.incubator.httpclient-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.httpclient-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.httpclient-B.sym.txt diff --git a/make/data/symbols/jdk.incubator.jpackage-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.jpackage-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.jpackage-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.jpackage-E.sym.txt diff --git a/make/data/symbols/jdk.incubator.jpackage-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.jpackage-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.jpackage-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.jpackage-G.sym.txt diff --git a/make/data/symbols/jdk.incubator.vector-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.vector-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.vector-G.sym.txt diff --git a/make/data/symbols/jdk.incubator.vector-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.vector-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.vector-H.sym.txt diff --git a/make/data/symbols/jdk.incubator.vector-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.incubator.vector-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.incubator.vector-I.sym.txt diff --git a/make/data/symbols/jdk.jartool-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-9.sym.txt diff --git a/make/data/symbols/jdk.jartool-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-A.sym.txt diff --git a/make/data/symbols/jdk.jartool-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-B.sym.txt diff --git a/make/data/symbols/jdk.jartool-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-D.sym.txt diff --git a/make/data/symbols/jdk.jartool-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-F.sym.txt diff --git a/make/data/symbols/jdk.jartool-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-G.sym.txt diff --git a/make/data/symbols/jdk.jartool-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-H.sym.txt diff --git a/make/data/symbols/jdk.jartool-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jartool-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jartool-I.sym.txt diff --git a/make/data/symbols/jdk.javadoc-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-9.sym.txt diff --git a/make/data/symbols/jdk.javadoc-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-A.sym.txt diff --git a/make/data/symbols/jdk.javadoc-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-B.sym.txt diff --git a/make/data/symbols/jdk.javadoc-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-D.sym.txt diff --git a/make/data/symbols/jdk.javadoc-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-F.sym.txt diff --git a/make/data/symbols/jdk.javadoc-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-G.sym.txt diff --git a/make/data/symbols/jdk.javadoc-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-H.sym.txt diff --git a/make/data/symbols/jdk.javadoc-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.javadoc-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.javadoc-I.sym.txt diff --git a/make/data/symbols/jdk.jcmd-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jcmd-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jcmd-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jcmd-9.sym.txt diff --git a/make/data/symbols/jdk.jcmd-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jcmd-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jcmd-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jcmd-A.sym.txt diff --git a/make/data/symbols/jdk.jcmd-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jcmd-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jcmd-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jcmd-B.sym.txt diff --git a/make/data/symbols/jdk.jconsole-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-9.sym.txt diff --git a/make/data/symbols/jdk.jconsole-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-A.sym.txt diff --git a/make/data/symbols/jdk.jconsole-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-B.sym.txt diff --git a/make/data/symbols/jdk.jconsole-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-G.sym.txt diff --git a/make/data/symbols/jdk.jconsole-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-H.sym.txt diff --git a/make/data/symbols/jdk.jconsole-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jconsole-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jconsole-I.sym.txt diff --git a/make/data/symbols/jdk.jdeps-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdeps-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdeps-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdeps-9.sym.txt diff --git a/make/data/symbols/jdk.jdeps-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdeps-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdeps-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdeps-A.sym.txt diff --git a/make/data/symbols/jdk.jdeps-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdeps-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdeps-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdeps-B.sym.txt diff --git a/make/data/symbols/jdk.jdi-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-9.sym.txt diff --git a/make/data/symbols/jdk.jdi-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-A.sym.txt diff --git a/make/data/symbols/jdk.jdi-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-B.sym.txt diff --git a/make/data/symbols/jdk.jdi-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-F.sym.txt diff --git a/make/data/symbols/jdk.jdi-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-G.sym.txt diff --git a/make/data/symbols/jdk.jdi-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-H.sym.txt diff --git a/make/data/symbols/jdk.jdi-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdi-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdi-I.sym.txt diff --git a/make/data/symbols/jdk.jdwp.agent-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdwp.agent-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-9.sym.txt diff --git a/make/data/symbols/jdk.jdwp.agent-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdwp.agent-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-A.sym.txt diff --git a/make/data/symbols/jdk.jdwp.agent-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jdwp.agent-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jdwp.agent-B.sym.txt diff --git a/make/data/symbols/jdk.jfr-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jfr-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jfr-B.sym.txt diff --git a/make/data/symbols/jdk.jfr-C.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-C.sym.txt similarity index 100% rename from make/data/symbols/jdk.jfr-C.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jfr-C.sym.txt diff --git a/make/data/symbols/jdk.jfr-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.jfr-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jfr-E.sym.txt diff --git a/make/data/symbols/jdk.jfr-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jfr-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jfr-G.sym.txt diff --git a/make/data/symbols/jdk.jfr-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jfr-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jfr-H.sym.txt diff --git a/make/data/symbols/jdk.jlink-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-9.sym.txt diff --git a/make/data/symbols/jdk.jlink-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-A.sym.txt diff --git a/make/data/symbols/jdk.jlink-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-B.sym.txt diff --git a/make/data/symbols/jdk.jlink-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-D.sym.txt diff --git a/make/data/symbols/jdk.jlink-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-E.sym.txt diff --git a/make/data/symbols/jdk.jlink-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jlink-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jlink-I.sym.txt diff --git a/make/data/symbols/jdk.jpackage-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jpackage-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jpackage-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jpackage-G.sym.txt diff --git a/make/data/symbols/jdk.jshell-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-9.sym.txt diff --git a/make/data/symbols/jdk.jshell-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-A.sym.txt diff --git a/make/data/symbols/jdk.jshell-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-B.sym.txt diff --git a/make/data/symbols/jdk.jshell-D.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-D.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-D.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-D.sym.txt diff --git a/make/data/symbols/jdk.jshell-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-E.sym.txt diff --git a/make/data/symbols/jdk.jshell-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-G.sym.txt diff --git a/make/data/symbols/jdk.jshell-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-H.sym.txt diff --git a/make/data/symbols/jdk.jshell-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jshell-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jshell-I.sym.txt diff --git a/make/data/symbols/jdk.jsobject-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-9.sym.txt diff --git a/make/data/symbols/jdk.jsobject-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-A.sym.txt diff --git a/make/data/symbols/jdk.jsobject-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-B.sym.txt diff --git a/make/data/symbols/jdk.jsobject-C.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-C.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-C.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-C.sym.txt diff --git a/make/data/symbols/jdk.jsobject-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-E.sym.txt diff --git a/make/data/symbols/jdk.jsobject-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-G.sym.txt diff --git a/make/data/symbols/jdk.jsobject-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-H.sym.txt diff --git a/make/data/symbols/jdk.jsobject-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.jsobject-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jsobject-I.sym.txt diff --git a/make/data/symbols/jdk.jstatd-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jstatd-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.jstatd-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jstatd-9.sym.txt diff --git a/make/data/symbols/jdk.jstatd-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jstatd-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.jstatd-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jstatd-A.sym.txt diff --git a/make/data/symbols/jdk.jstatd-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jstatd-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.jstatd-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.jstatd-B.sym.txt diff --git a/make/data/symbols/jdk.localedata-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.localedata-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.localedata-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.localedata-9.sym.txt diff --git a/make/data/symbols/jdk.localedata-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.localedata-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.localedata-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.localedata-A.sym.txt diff --git a/make/data/symbols/jdk.localedata-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.localedata-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.localedata-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.localedata-B.sym.txt diff --git a/make/data/symbols/jdk.management-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-7.sym.txt diff --git a/make/data/symbols/jdk.management-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt diff --git a/make/data/symbols/jdk.management-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt diff --git a/make/data/symbols/jdk.management-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-A.sym.txt diff --git a/make/data/symbols/jdk.management-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-B.sym.txt diff --git a/make/data/symbols/jdk.management-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-E.sym.txt diff --git a/make/data/symbols/jdk.management-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-G.sym.txt diff --git a/make/data/symbols/jdk.management-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-H.sym.txt diff --git a/make/data/symbols/jdk.management-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.management-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management-I.sym.txt diff --git a/make/data/symbols/jdk.management.agent-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.agent-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.agent-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.agent-9.sym.txt diff --git a/make/data/symbols/jdk.management.agent-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.agent-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.agent-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.agent-A.sym.txt diff --git a/make/data/symbols/jdk.management.agent-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.agent-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.agent-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.agent-B.sym.txt diff --git a/make/data/symbols/jdk.management.jfr-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.jfr-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.jfr-B.sym.txt diff --git a/make/data/symbols/jdk.management.jfr-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.jfr-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.jfr-G.sym.txt diff --git a/make/data/symbols/jdk.management.jfr-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.jfr-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.jfr-H.sym.txt diff --git a/make/data/symbols/jdk.management.jfr-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.management.jfr-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.management.jfr-I.sym.txt diff --git a/make/data/symbols/jdk.naming.dns-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.dns-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.dns-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.dns-9.sym.txt diff --git a/make/data/symbols/jdk.naming.dns-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.dns-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.dns-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.dns-A.sym.txt diff --git a/make/data/symbols/jdk.naming.dns-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.dns-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.dns-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.dns-B.sym.txt diff --git a/make/data/symbols/jdk.naming.rmi-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.rmi-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.rmi-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.rmi-9.sym.txt diff --git a/make/data/symbols/jdk.naming.rmi-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.rmi-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.rmi-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.rmi-A.sym.txt diff --git a/make/data/symbols/jdk.naming.rmi-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.naming.rmi-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.naming.rmi-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.naming.rmi-B.sym.txt diff --git a/make/data/symbols/jdk.net-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt diff --git a/make/data/symbols/jdk.net-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-A.sym.txt diff --git a/make/data/symbols/jdk.net-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-B.sym.txt diff --git a/make/data/symbols/jdk.net-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-E.sym.txt diff --git a/make/data/symbols/jdk.net-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-F.sym.txt diff --git a/make/data/symbols/jdk.net-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-G.sym.txt diff --git a/make/data/symbols/jdk.net-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-H.sym.txt diff --git a/make/data/symbols/jdk.net-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.net-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.net-I.sym.txt diff --git a/make/data/symbols/jdk.nio.mapmode-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.nio.mapmode-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.nio.mapmode-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.nio.mapmode-F.sym.txt diff --git a/make/data/symbols/jdk.pack-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.pack-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.pack-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.pack-9.sym.txt diff --git a/make/data/symbols/jdk.pack-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.pack-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.pack-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.pack-A.sym.txt diff --git a/make/data/symbols/jdk.pack-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.pack-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.pack-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.pack-B.sym.txt diff --git a/make/data/symbols/jdk.pack-E.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.pack-E.sym.txt similarity index 100% rename from make/data/symbols/jdk.pack-E.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.pack-E.sym.txt diff --git a/make/data/symbols/jdk.policytool-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.policytool-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.policytool-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.policytool-9.sym.txt diff --git a/make/data/symbols/jdk.policytool-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.policytool-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.policytool-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.policytool-A.sym.txt diff --git a/make/data/symbols/jdk.rmic-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.rmic-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.rmic-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.rmic-9.sym.txt diff --git a/make/data/symbols/jdk.rmic-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.rmic-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.rmic-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.rmic-A.sym.txt diff --git a/make/data/symbols/jdk.rmic-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.rmic-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.rmic-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.rmic-B.sym.txt diff --git a/make/data/symbols/jdk.rmic-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.rmic-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.rmic-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.rmic-F.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-7.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-8.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-9.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-A.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-B.sym.txt diff --git a/make/data/symbols/jdk.scripting.nashorn-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.scripting.nashorn-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.scripting.nashorn-F.sym.txt diff --git a/make/data/symbols/jdk.sctp-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-7.sym.txt diff --git a/make/data/symbols/jdk.sctp-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-8.sym.txt diff --git a/make/data/symbols/jdk.sctp-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-9.sym.txt diff --git a/make/data/symbols/jdk.sctp-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-A.sym.txt diff --git a/make/data/symbols/jdk.sctp-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-B.sym.txt diff --git a/make/data/symbols/jdk.sctp-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-G.sym.txt diff --git a/make/data/symbols/jdk.sctp-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-H.sym.txt diff --git a/make/data/symbols/jdk.sctp-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.sctp-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.sctp-I.sym.txt diff --git a/make/data/symbols/jdk.security.auth-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-7.sym.txt diff --git a/make/data/symbols/jdk.security.auth-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-8.sym.txt diff --git a/make/data/symbols/jdk.security.auth-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-9.sym.txt diff --git a/make/data/symbols/jdk.security.auth-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-A.sym.txt diff --git a/make/data/symbols/jdk.security.auth-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-B.sym.txt diff --git a/make/data/symbols/jdk.security.auth-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-G.sym.txt diff --git a/make/data/symbols/jdk.security.auth-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-H.sym.txt diff --git a/make/data/symbols/jdk.security.auth-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.auth-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.auth-I.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-7.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-7.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-7.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-7.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-8.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-8.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-8.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-9.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-A.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-B.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-G.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-H.sym.txt diff --git a/make/data/symbols/jdk.security.jgss-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.security.jgss-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.security.jgss-I.sym.txt diff --git a/make/data/symbols/jdk.unsupported-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-9.sym.txt diff --git a/make/data/symbols/jdk.unsupported-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-A.sym.txt diff --git a/make/data/symbols/jdk.unsupported-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-B.sym.txt diff --git a/make/data/symbols/jdk.unsupported-C.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-C.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-C.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-C.sym.txt diff --git a/make/data/symbols/jdk.unsupported-F.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-F.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-F.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-F.sym.txt diff --git a/make/data/symbols/jdk.unsupported-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-G.sym.txt diff --git a/make/data/symbols/jdk.unsupported-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-H.sym.txt diff --git a/make/data/symbols/jdk.unsupported-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.unsupported-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.unsupported-I.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-9.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-A.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-B.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-G.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-G.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-G.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-G.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-H.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-H.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-H.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-H.sym.txt diff --git a/make/data/symbols/jdk.xml.dom-I.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-I.sym.txt similarity index 100% rename from make/data/symbols/jdk.xml.dom-I.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.xml.dom-I.sym.txt diff --git a/make/data/symbols/jdk.zipfs-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.zipfs-9.sym.txt similarity index 100% rename from make/data/symbols/jdk.zipfs-9.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.zipfs-9.sym.txt diff --git a/make/data/symbols/jdk.zipfs-A.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.zipfs-A.sym.txt similarity index 100% rename from make/data/symbols/jdk.zipfs-A.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.zipfs-A.sym.txt diff --git a/make/data/symbols/jdk.zipfs-B.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.zipfs-B.sym.txt similarity index 100% rename from make/data/symbols/jdk.zipfs-B.sym.txt rename to src/jdk.compiler/share/data/symbols/jdk.zipfs-B.sym.txt diff --git a/make/data/symbols/symbols b/src/jdk.compiler/share/data/symbols/symbols similarity index 100% rename from make/data/symbols/symbols rename to src/jdk.compiler/share/data/symbols/symbols diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java index c7552402509313ad98521793f77c4656c47a3316..5bc199b55ad4b7b3fa3f0137fadfb3b0080e22dc 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.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 @@ -30,6 +30,7 @@ import java.security.spec.AlgorithmParameterSpec; import javax.crypto.*; +import sun.security.util.SecurityProviderConstants; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; @@ -225,7 +226,8 @@ final class P11KeyGenerator extends KeyGeneratorSpi { significantKeySize = 168; break; case (int)CKM_AES_KEY_GEN: - keySize = adjustKeySize(128, range); + keySize = adjustKeySize + (SecurityProviderConstants.getDefAESKeySize(), range); keyType = CKK_AES; break; case (int)CKM_RC4_KEY_GEN: diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java index f13ae3cd67ddcad436de77bf6f808f3a1829dd41..ba99d0bcb5c13b67e88cc06093b5ba07e1e02d15 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.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 @@ -99,29 +99,35 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { // set default key sizes and apply our own algorithm-specific limits // override lower limit to disallow unsecure keys being generated // override upper limit to deter DOS attack - if (algorithm.equals("EC")) { - keySize = DEF_EC_KEY_SIZE; - if (minKeyLen < 112) { - minKeyLen = 112; - } - if (maxKeyLen > 2048) { - maxKeyLen = 2048; + int jdkMinKeyLen = 512; + int jdkMaxKeyLen = Integer.MAX_VALUE; + switch (algorithm) { + case "EC" -> { + keySize = DEF_EC_KEY_SIZE; + jdkMinKeyLen = 112; + jdkMaxKeyLen = 2048; } - } else { - if (algorithm.equals("DSA")) { + case "DSA" -> { keySize = DEF_DSA_KEY_SIZE; - } else if (algorithm.equals("RSA")) { + } + case "RSA" -> { keySize = DEF_RSA_KEY_SIZE; - if (maxKeyLen > 64 * 1024) { - maxKeyLen = 64 * 1024; - } - } else { + jdkMaxKeyLen = 64 * 1024; + } + case "DH" -> { keySize = DEF_DH_KEY_SIZE; } - if (minKeyLen < 512) { - minKeyLen = 512; + default -> { + throw new ProviderException + ("Unrecognized algorithm for checking key size"); } } + if (minKeyLen < jdkMinKeyLen) { + minKeyLen = jdkMinKeyLen; + } + if (maxKeyLen > jdkMaxKeyLen) { + maxKeyLen = jdkMaxKeyLen; + } // auto-adjust default keysize in case it's out-of-range if (keySize < minKeyLen) { diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp index b7a2c6dde8fe56c4184f747a5d62aa4956ff8599..9accba375a2553020d96a7e9c2f0f427683b919e 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp @@ -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. * Copyright (c) 2019, 2021, NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -60,6 +60,10 @@ #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h" #endif +#ifdef riscv64 +#include "sun_jvm_hotspot_debugger_riscv64_RISCV64ThreadContext.h" +#endif + class AutoJavaString { JNIEnv* m_env; jstring m_str; @@ -408,7 +412,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo return (err == PS_OK)? array : 0; } -#if defined(i586) || defined(amd64) || defined(ppc64) || defined(ppc64le) || defined(aarch64) +#if defined(i586) || defined(amd64) || defined(ppc64) || defined(ppc64le) || defined(aarch64) || defined(riscv64) extern "C" JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -440,6 +444,9 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #ifdef aarch64 #define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG #endif +#ifdef riscv64 +#define NPRGREG sun_jvm_hotspot_debugger_riscv64_RISCV64ThreadContext_NPRGREG +#endif #if defined(ppc64) || defined(ppc64le) #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG #endif @@ -516,6 +523,44 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo } #endif /* aarch64 */ +#if defined(riscv64) +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_riscv64_RISCV64ThreadContext_##reg + + regs[REG_INDEX(PC)] = gregs.pc; + regs[REG_INDEX(LR)] = gregs.ra; + regs[REG_INDEX(SP)] = gregs.sp; + regs[REG_INDEX(R3)] = gregs.gp; + regs[REG_INDEX(R4)] = gregs.tp; + regs[REG_INDEX(R5)] = gregs.t0; + regs[REG_INDEX(R6)] = gregs.t1; + regs[REG_INDEX(R7)] = gregs.t2; + regs[REG_INDEX(R8)] = gregs.s0; + regs[REG_INDEX(R9)] = gregs.s1; + regs[REG_INDEX(R10)] = gregs.a0; + regs[REG_INDEX(R11)] = gregs.a1; + regs[REG_INDEX(R12)] = gregs.a2; + regs[REG_INDEX(R13)] = gregs.a3; + regs[REG_INDEX(R14)] = gregs.a4; + regs[REG_INDEX(R15)] = gregs.a5; + regs[REG_INDEX(R16)] = gregs.a6; + regs[REG_INDEX(R17)] = gregs.a7; + regs[REG_INDEX(R18)] = gregs.s2; + regs[REG_INDEX(R19)] = gregs.s3; + regs[REG_INDEX(R20)] = gregs.s4; + regs[REG_INDEX(R21)] = gregs.s5; + regs[REG_INDEX(R22)] = gregs.s6; + regs[REG_INDEX(R23)] = gregs.s7; + regs[REG_INDEX(R24)] = gregs.s8; + regs[REG_INDEX(R25)] = gregs.s9; + regs[REG_INDEX(R26)] = gregs.s10; + regs[REG_INDEX(R27)] = gregs.s11; + regs[REG_INDEX(R28)] = gregs.t3; + regs[REG_INDEX(R29)] = gregs.t4; + regs[REG_INDEX(R30)] = gregs.t5; + regs[REG_INDEX(R31)] = gregs.t6; + +#endif /* riscv64 */ + #if defined(ppc64) || defined(ppc64le) #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h index b0fcfb1e4d59b97aaad6d9199c98970f92530705..a69496e77a4d46ee4593ae6d4a996189ad2dad0e 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,8 @@ #elif defined(arm) #include #define user_regs_struct pt_regs +#elif defined(riscv64) +#include #endif // This C bool type must be int for compatibility with Linux calls and diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java index 04db854c84d03f2e064e3ee8305a437e19856478..12983fc93cdfaea0e1bc74d879a1be167bd669e9 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java @@ -36,6 +36,7 @@ import sun.jvm.hotspot.debugger.MachineDescription; import sun.jvm.hotspot.debugger.MachineDescriptionAMD64; import sun.jvm.hotspot.debugger.MachineDescriptionPPC64; import sun.jvm.hotspot.debugger.MachineDescriptionAArch64; +import sun.jvm.hotspot.debugger.MachineDescriptionRISCV64; import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86; import sun.jvm.hotspot.debugger.NoSuchSymbolException; import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal; @@ -476,12 +477,8 @@ public class HotSpotAgent { throw new DebuggerException("Cannot find alternate SA Debugger: '" + alternateName + "'"); } catch (NoSuchMethodException nsme) { throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' has missing constructor."); - } catch (InstantiationException ie) { - throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", ie); - } catch (IllegalAccessException iae) { - throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", iae); - } catch (InvocationTargetException iae) { - throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", iae); + } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { + throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", e); } System.err.println("Loaded alternate HotSpot SA Debugger: " + alternateName); @@ -558,6 +555,8 @@ public class HotSpotAgent { machDesc = new MachineDescriptionPPC64(); } else if (cpu.equals("aarch64")) { machDesc = new MachineDescriptionAArch64(); + } else if (cpu.equals("riscv64")) { + machDesc = new MachineDescriptionRISCV64(); } else { try { machDesc = (MachineDescription) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java similarity index 65% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java rename to src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java index 3d96d33d81e8974677bbfb23676689472da2c895..a972516dee3b0e418da8a1e383c5571ed656ce9e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,19 +23,18 @@ * */ -package sun.jvm.hotspot.gc.shared; +package sun.jvm.hotspot.debugger; -import sun.jvm.hotspot.debugger.*; - -/** Class CardGeneration is a generation that is covered by a card - table, and uses a card-size block-offset array to implement - block_start. */ +public class MachineDescriptionRISCV64 extends MachineDescriptionTwosComplement implements MachineDescription { + public long getAddressSize() { + return 8; + } -public abstract class CardGeneration extends Generation { - public CardGeneration(Address addr) { - super(addr); + public boolean isLP64() { + return true; } - // FIXME: not sure what I need to expose from here in order to have - // verification similar to that of the old RememberedSet + public boolean isBigEndian() { + return false; + } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java index 491e3d5dc2c007f50772df4b60ce76105778c8d2..469bb6e0665557f053985688d4a921b858aa0f49 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.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. * Copyright (c) 2015, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,11 +33,13 @@ import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.x86.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.debugger.aarch64.*; +import sun.jvm.hotspot.debugger.riscv64.*; import sun.jvm.hotspot.debugger.ppc64.*; import sun.jvm.hotspot.debugger.linux.x86.*; import sun.jvm.hotspot.debugger.linux.amd64.*; import sun.jvm.hotspot.debugger.linux.ppc64.*; import sun.jvm.hotspot.debugger.linux.aarch64.*; +import sun.jvm.hotspot.debugger.linux.riscv64.*; import sun.jvm.hotspot.utilities.*; class LinuxCDebugger implements CDebugger { @@ -105,7 +107,14 @@ class LinuxCDebugger implements CDebugger { Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC); if (pc == null) return null; return new LinuxAARCH64CFrame(dbg, fp, pc); - } else { + } else if (cpu.equals("riscv64")) { + RISCV64ThreadContext context = (RISCV64ThreadContext) thread.getContext(); + Address fp = context.getRegisterAsAddress(RISCV64ThreadContext.FP); + if (fp == null) return null; + Address pc = context.getRegisterAsAddress(RISCV64ThreadContext.PC); + if (pc == null) return null; + return new LinuxRISCV64CFrame(dbg, fp, pc); + } else { // Runtime exception thrown by LinuxThreadContextFactory if unknown cpu ThreadContext context = (ThreadContext) thread.getContext(); return context.getTopFrame(dbg); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java new file mode 100644 index 0000000000000000000000000000000000000000..f06da24bd0e30e8e442de1fffe824f5f5fef164b --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.linux.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.linux.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.cdbg.basic.*; + +public final class LinuxRISCV64CFrame extends BasicCFrame { + private static final int C_FRAME_LINK_OFFSET = -2; + private static final int C_FRAME_RETURN_ADDR_OFFSET = -1; + + public LinuxRISCV64CFrame(LinuxDebugger dbg, Address fp, Address pc) { + super(dbg.getCDebugger()); + this.fp = fp; + this.pc = pc; + this.dbg = dbg; + } + + // override base class impl to avoid ELF parsing + public ClosestSymbol closestSymbolToPC() { + // try native lookup in debugger. + return dbg.lookup(dbg.getAddressValue(pc())); + } + + public Address pc() { + return pc; + } + + public Address localVariableBase() { + return fp; + } + + public CFrame sender(ThreadProxy thread) { + RISCV64ThreadContext context = (RISCV64ThreadContext) thread.getContext(); + Address rsp = context.getRegisterAsAddress(RISCV64ThreadContext.SP); + + if ((fp == null) || fp.lessThan(rsp)) { + return null; + } + + // Check alignment of fp + if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) { + return null; + } + + Address nextFP = fp.getAddressAt(C_FRAME_LINK_OFFSET * ADDRESS_SIZE); + if (nextFP == null || nextFP.lessThanOrEqual(fp)) { + return null; + } + Address nextPC = fp.getAddressAt(C_FRAME_RETURN_ADDR_OFFSET * ADDRESS_SIZE); + if (nextPC == null) { + return null; + } + return new LinuxRISCV64CFrame(dbg, nextFP, nextPC); + } + + // package/class internals only + private static final int ADDRESS_SIZE = 8; + private Address pc; + private Address sp; + private Address fp; + private LinuxDebugger dbg; +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java new file mode 100644 index 0000000000000000000000000000000000000000..fdb841ccf3dbcb43bd686a2ab17aab9c89bb664e --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.linux.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.linux.*; + +public class LinuxRISCV64ThreadContext extends RISCV64ThreadContext { + private LinuxDebugger debugger; + + public LinuxRISCV64ThreadContext(LinuxDebugger debugger) { + super(); + this.debugger = debugger; + } + + public void setRegisterAsAddress(int index, Address value) { + setRegister(index, debugger.getAddressValue(value)); + } + + public Address getRegisterAsAddress(int index) { + return debugger.newAddress(getRegister(index)); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java new file mode 100644 index 0000000000000000000000000000000000000000..96d5dee47cee343d2b45f038534bd3e4c6b98bff --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.proc.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.proc.*; +import sun.jvm.hotspot.utilities.*; + +public class ProcRISCV64Thread implements ThreadProxy { + private ProcDebugger debugger; + private int id; + + public ProcRISCV64Thread(ProcDebugger debugger, Address addr) { + this.debugger = debugger; + + // FIXME: the size here should be configurable. However, making it + // so would produce a dependency on the "types" package from the + // debugger package, which is not desired. + this.id = (int) addr.getCIntegerAt(0, 4, true); + } + + public ProcRISCV64Thread(ProcDebugger debugger, long id) { + this.debugger = debugger; + this.id = (int) id; + } + + public ThreadContext getContext() throws IllegalThreadStateException { + ProcRISCV64ThreadContext context = new ProcRISCV64ThreadContext(debugger); + long[] regs = debugger.getThreadIntegerRegisterSet(id); + if (Assert.ASSERTS_ENABLED) { + Assert.that(regs.length == RISCV64ThreadContext.NPRGREG, "size mismatch"); + } + for (int i = 0; i < regs.length; i++) { + context.setRegister(i, regs[i]); + } + return context; + } + + public boolean canSetContext() throws DebuggerException { + return false; + } + + public void setContext(ThreadContext context) + throws IllegalThreadStateException, DebuggerException { + throw new DebuggerException("Unimplemented"); + } + + public String toString() { + return "t@" + id; + } + + public boolean equals(Object obj) { + if ((obj == null) || !(obj instanceof ProcRISCV64Thread)) { + return false; + } + + return (((ProcRISCV64Thread) obj).id == id); + } + + public int hashCode() { + return id; + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java new file mode 100644 index 0000000000000000000000000000000000000000..f2aa845e665c84a3e9f3cf05c78ba4e2579828db --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.proc.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.proc.*; + +public class ProcRISCV64ThreadContext extends RISCV64ThreadContext { + private ProcDebugger debugger; + + public ProcRISCV64ThreadContext(ProcDebugger debugger) { + super(); + this.debugger = debugger; + } + + public void setRegisterAsAddress(int index, Address value) { + setRegister(index, debugger.getAddressValue(value)); + } + + public Address getRegisterAsAddress(int index) { + return debugger.newAddress(getRegister(index)); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..19f64b8ce2dc8bb70e69b77db93479f59fb1d419 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.proc.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.proc.*; + +public class ProcRISCV64ThreadFactory implements ProcThreadFactory { + private ProcDebugger debugger; + + public ProcRISCV64ThreadFactory(ProcDebugger debugger) { + this.debugger = debugger; + } + + public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { + return new ProcRISCV64Thread(debugger, threadIdentifierAddr); + } + + public ThreadProxy createThreadWrapper(long id) { + return new ProcRISCV64Thread(debugger, id); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java new file mode 100644 index 0000000000000000000000000000000000000000..aecbda590238ac40b3450f6c1ea88fcf132df9e3 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.remote.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.remote.*; +import sun.jvm.hotspot.utilities.*; + +public class RemoteRISCV64Thread extends RemoteThread { + public RemoteRISCV64Thread(RemoteDebuggerClient debugger, Address addr) { + super(debugger, addr); + } + + public RemoteRISCV64Thread(RemoteDebuggerClient debugger, long id) { + super(debugger, id); + } + + public ThreadContext getContext() throws IllegalThreadStateException { + RemoteRISCV64ThreadContext context = new RemoteRISCV64ThreadContext(debugger); + long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) : + debugger.getThreadIntegerRegisterSet(id); + if (Assert.ASSERTS_ENABLED) { + Assert.that(regs.length == RISCV64ThreadContext.NPRGREG, "size of register set must match"); + } + for (int i = 0; i < regs.length; i++) { + context.setRegister(i, regs[i]); + } + return context; + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java new file mode 100644 index 0000000000000000000000000000000000000000..1d3da6be5afe1dff774bb6edf0a67601bb2cb770 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.remote.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.debugger.remote.*; + +public class RemoteRISCV64ThreadContext extends RISCV64ThreadContext { + private RemoteDebuggerClient debugger; + + public RemoteRISCV64ThreadContext(RemoteDebuggerClient debugger) { + super(); + this.debugger = debugger; + } + + public void setRegisterAsAddress(int index, Address value) { + setRegister(index, debugger.getAddressValue(value)); + } + + public Address getRegisterAsAddress(int index) { + return debugger.newAddress(getRegister(index)); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..725b94e25a31e2527aae984aa7e92ffeac731dbc --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.remote.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.remote.*; + +public class RemoteRISCV64ThreadFactory implements RemoteThreadFactory { + private RemoteDebuggerClient debugger; + + public RemoteRISCV64ThreadFactory(RemoteDebuggerClient debugger) { + this.debugger = debugger; + } + + public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { + return new RemoteRISCV64Thread(debugger, threadIdentifierAddr); + } + + public ThreadProxy createThreadWrapper(long id) { + return new RemoteRISCV64Thread(debugger, id); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java new file mode 100644 index 0000000000000000000000000000000000000000..fb60a70427a5f455a3198c1f09a1d3ef4193c9a7 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.debugger.riscv64; + +import java.lang.annotation.Native; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; + +/** Specifies the thread context on riscv64 platforms; only a sub-portion + * of the context is guaranteed to be present on all operating + * systems. */ + +public abstract class RISCV64ThreadContext implements ThreadContext { + // Taken from /usr/include/asm/sigcontext.h on Linux/RISCV64. + + // /* + // * Signal context structure - contains all info to do with the state + // * before the signal handler was invoked. + // */ + // struct sigcontext { + // struct user_regs_struct sc_regs; + // union __riscv_fp_state sc_fpregs; + // }; + // + // struct user_regs_struct { + // unsigned long pc; + // unsigned long ra; + // unsigned long sp; + // unsigned long gp; + // unsigned long tp; + // unsigned long t0; + // unsigned long t1; + // unsigned long t2; + // unsigned long s0; + // unsigned long s1; + // unsigned long a0; + // unsigned long a1; + // unsigned long a2; + // unsigned long a3; + // unsigned long a4; + // unsigned long a5; + // unsigned long a6; + // unsigned long a7; + // unsigned long s2; + // unsigned long s3; + // unsigned long s4; + // unsigned long s5; + // unsigned long s6; + // unsigned long s7; + // unsigned long s8; + // unsigned long s9; + // unsigned long s10; + // unsigned long s11; + // unsigned long t3; + // unsigned long t4; + // unsigned long t5; + // unsigned long t6; + // }; + + // NOTE: the indices for the various registers must be maintained as + // listed across various operating systems. However, only a small + // subset of the registers' values are guaranteed to be present (and + // must be present for the SA's stack walking to work) + + // One instance of the Native annotation is enough to trigger header generation + // for this file. + @Native + public static final int R0 = 0; + public static final int R1 = 1; + public static final int R2 = 2; + public static final int R3 = 3; + public static final int R4 = 4; + public static final int R5 = 5; + public static final int R6 = 6; + public static final int R7 = 7; + public static final int R8 = 8; + public static final int R9 = 9; + public static final int R10 = 10; + public static final int R11 = 11; + public static final int R12 = 12; + public static final int R13 = 13; + public static final int R14 = 14; + public static final int R15 = 15; + public static final int R16 = 16; + public static final int R17 = 17; + public static final int R18 = 18; + public static final int R19 = 19; + public static final int R20 = 20; + public static final int R21 = 21; + public static final int R22 = 22; + public static final int R23 = 23; + public static final int R24 = 24; + public static final int R25 = 25; + public static final int R26 = 26; + public static final int R27 = 27; + public static final int R28 = 28; + public static final int R29 = 29; + public static final int R30 = 30; + public static final int R31 = 31; + + public static final int NPRGREG = 32; + + public static final int PC = R0; + public static final int LR = R1; + public static final int SP = R2; + public static final int FP = R8; + + private long[] data; + + public RISCV64ThreadContext() { + data = new long[NPRGREG]; + } + + public int getNumRegisters() { + return NPRGREG; + } + + public String getRegisterName(int index) { + switch (index) { + case LR: return "lr"; + case SP: return "sp"; + case PC: return "pc"; + default: + return "r" + index; + } + } + + public void setRegister(int index, long value) { + data[index] = value; + } + + public long getRegister(int index) { + return data[index]; + } + + public CFrame getTopFrame(Debugger dbg) { + return null; + } + + /** This can't be implemented in this class since we would have to + * tie the implementation to, for example, the debugging system */ + public abstract void setRegisterAsAddress(int index, Address value); + + /** This can't be implemented in this class since we would have to + * tie the implementation to, for example, the debugging system */ + public abstract Address getRegisterAsAddress(int index); +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java index 10ac92556369283b6bf38794f43b74aa65410c91..198f5ca6d07faba747fbba67c483237a5ece7254 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.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 @@ -76,8 +76,6 @@ public class COFFFileParser { // a bug if there is one. (FIXME) // buf.order(ByteOrder.nativeOrder()); return parse(new MappedByteBufferDataSource(buf)); - } catch (FileNotFoundException e) { - throw new COFFException(e); } catch (IOException e) { throw new COFFException(e); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java index 6f121f963af17f69ff31bd4acb94c14cff0ed8de..cc4f216efc2047b4266d44fdb0f17fd61987ba17 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java @@ -39,7 +39,7 @@ import sun.jvm.hotspot.utilities.Observer;

    Garbage collection is performed using mark-compact.

    */ -public class TenuredGeneration extends CardGeneration { +public class TenuredGeneration extends Generation { private static AddressField theSpaceField; static { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java index eeb099a11dca80539d544f4f8d442363d9ad6cf3..5323d9cee4e9d10979d11051dbfa6cf6b8f4adfa 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java @@ -38,10 +38,7 @@ import sun.jvm.hotspot.utilities.Observer;
    • Generation
        -
      • CardGeneration -
          -
        • TenuredGeneration -
        +
      • TenuredGeneration
      • DefNewGeneration
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java index 5f129b51a969237c940cf170d0be7d35c8f5494b..8e1c005d6a1796d77082e858f602652a9a3e59a5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java @@ -78,7 +78,7 @@ public class ZGlobals { ZPageSizeMediumShift = db.lookupLongConstant("ZPageSizeMediumShift").longValue(); ZObjectAlignmentMediumShift = db.lookupIntConstant("ZObjectAlignmentMediumShift").intValue(); - ZObjectAlignmentLargeShift = db.lookupIntConstant("ZObjectAlignmentLargeShift").intValue();; + ZObjectAlignmentLargeShift = db.lookupIntConstant("ZObjectAlignmentLargeShift").intValue(); ZAddressOffsetShift = db.lookupLongConstant("ZAddressOffsetShift").longValue(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java index b091afece874b1d3f21f89e3aeaa0a3f8db82fff..355f78e44060061e99c1fbe77f8028be6b7a06c8 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java @@ -34,8 +34,6 @@ public class Thread extends VMObject { private static long tlabFieldOffset; private static CIntegerField suspendFlagsField; - // Thread::SuspendFlags enum constants - private static int HAS_ASYNC_EXCEPTION; private static AddressField currentPendingMonitorField; private static AddressField currentWaitingMonitorField; @@ -55,7 +53,6 @@ public class Thread extends VMObject { Type typeJavaThread = db.lookupType("JavaThread"); suspendFlagsField = typeJavaThread.getCIntegerField("_suspend_flags"); - HAS_ASYNC_EXCEPTION = db.lookupIntConstant("JavaThread::_has_async_exception").intValue(); tlabFieldOffset = typeThread.getField("_tlab").getOffset(); currentPendingMonitorField = typeJavaThread.getAddressField("_current_pending_monitor"); @@ -71,10 +68,6 @@ public class Thread extends VMObject { return (int) suspendFlagsField.getValue(addr); } - public boolean hasAsyncException() { - return (suspendFlags() & HAS_ASYNC_EXCEPTION) != 0; - } - public ThreadLocalAllocBuffer tlab() { return new ThreadLocalAllocBuffer(addr.addOffsetTo(tlabFieldOffset)); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java index 4a2fa691d3ff6180c61d45b728632ef6a132c7ba..d16ac8aae518633cdc78fc204893809ead67c54c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.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,6 +34,7 @@ import sun.jvm.hotspot.runtime.win32_aarch64.Win32AARCH64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess; +import sun.jvm.hotspot.runtime.linux_riscv64.LinuxRISCV64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; @@ -113,6 +114,8 @@ public class Threads { access = new LinuxPPC64JavaThreadPDAccess(); } else if (cpu.equals("aarch64")) { access = new LinuxAARCH64JavaThreadPDAccess(); + } else if (cpu.equals("riscv64")) { + access = new LinuxRISCV64JavaThreadPDAccess(); } else { try { access = (JavaThreadPDAccess) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java new file mode 100644 index 0000000000000000000000000000000000000000..f2e224f28eeaa5be7f431bed226c5b300c0c8910 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.linux_riscv64; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.riscv64.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.utilities.Observable; +import sun.jvm.hotspot.utilities.Observer; + +public class LinuxRISCV64JavaThreadPDAccess implements JavaThreadPDAccess { + private static AddressField lastJavaFPField; + private static AddressField osThreadField; + + // Field from OSThread + private static CIntegerField osThreadThreadIDField; + + // This is currently unneeded but is being kept in case we change + // the currentFrameGuess algorithm + private static final long GUESS_SCAN_RANGE = 128 * 1024; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("JavaThread"); + osThreadField = type.getAddressField("_osthread"); + + Type anchorType = db.lookupType("JavaFrameAnchor"); + lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); + + Type osThreadType = db.lookupType("OSThread"); + osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + } + + public Address getLastJavaFP(Address addr) { + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset())); + } + + public Address getLastJavaPC(Address addr) { + return null; + } + + public Address getBaseOfStackPointer(Address addr) { + return null; + } + + public Frame getLastFramePD(JavaThread thread, Address addr) { + Address fp = thread.getLastJavaFP(); + if (fp == null) { + return null; // no information + } + return new RISCV64Frame(thread.getLastJavaSP(), fp); + } + + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { + return new RISCV64RegisterMap(thread, updateMap); + } + + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { + ThreadProxy t = getThreadProxy(addr); + RISCV64ThreadContext context = (RISCV64ThreadContext) t.getContext(); + RISCV64CurrentFrameGuess guesser = new RISCV64CurrentFrameGuess(context, thread); + if (!guesser.run(GUESS_SCAN_RANGE)) { + return null; + } + if (guesser.getPC() == null) { + return new RISCV64Frame(guesser.getSP(), guesser.getFP()); + } else { + return new RISCV64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + } + } + + public void printThreadIDOn(Address addr, PrintStream tty) { + tty.print(getThreadProxy(addr)); + } + + public void printInfoOn(Address threadAddr, PrintStream tty) { + tty.print("Thread id: "); + printThreadIDOn(threadAddr, tty); + } + + public Address getLastSP(Address addr) { + ThreadProxy t = getThreadProxy(addr); + RISCV64ThreadContext context = (RISCV64ThreadContext) t.getContext(); + return context.getRegisterAsAddress(RISCV64ThreadContext.SP); + } + + public ThreadProxy getThreadProxy(Address addr) { + // Addr is the address of the JavaThread. + // Fetch the OSThread (for now and for simplicity, not making a + // separate "OSThread" class in this package) + Address osThreadAddr = osThreadField.getValue(addr); + // Get the address of the _thread_id from the OSThread + Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); + + JVMDebugger debugger = VM.getVM().getDebugger(); + return debugger.getThreadForIdentifierAddress(threadIdAddr); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java new file mode 100644 index 0000000000000000000000000000000000000000..34701c6922f3deaad09c9cb8d08165a7a55af82d --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.riscv64.*; +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.interpreter.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.riscv64.*; + +/**

    Should be able to be used on all riscv64 platforms we support + (Linux/riscv64) to implement JavaThread's "currentFrameGuess()" + functionality. Input is an RISCV64ThreadContext; output is SP, FP, + and PC for an RISCV64Frame. Instantiation of the RISCV64Frame is + left to the caller, since we may need to subclass RISCV64Frame to + support signal handler frames on Unix platforms.

    + +

    Algorithm is to walk up the stack within a given range (say, + 512K at most) looking for a plausible PC and SP for a Java frame, + also considering those coming in from the context. If we find a PC + that belongs to the VM (i.e., in generated code like the + interpreter or CodeCache) then we try to find an associated FP. + We repeat this until we either find a complete frame or run out of + stack to look at.

    */ + +public class RISCV64CurrentFrameGuess { + private RISCV64ThreadContext context; + private JavaThread thread; + private Address spFound; + private Address fpFound; + private Address pcFound; + + private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.riscv64.RISCV64Frame.DEBUG") + != null; + + public RISCV64CurrentFrameGuess(RISCV64ThreadContext context, + JavaThread thread) { + this.context = context; + this.thread = thread; + } + + /** Returns false if not able to find a frame within a reasonable range. */ + public boolean run(long regionInBytesToSearch) { + Address sp = context.getRegisterAsAddress(RISCV64ThreadContext.SP); + Address pc = context.getRegisterAsAddress(RISCV64ThreadContext.PC); + Address fp = context.getRegisterAsAddress(RISCV64ThreadContext.FP); + if (sp == null) { + // Bail out if no last java frame either + if (thread.getLastJavaSP() != null) { + setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); + return true; + } + return false; + } + Address end = sp.addOffsetTo(regionInBytesToSearch); + VM vm = VM.getVM(); + + setValues(null, null, null); // Assume we're not going to find anything + + if (vm.isJavaPCDbg(pc)) { + if (vm.isClientCompiler()) { + // If the topmost frame is a Java frame, we are (pretty much) + // guaranteed to have a viable FP. We should be more robust + // than this (we have the potential for losing entire threads' + // stack traces) but need to see how much work we really have + // to do here. Searching the stack for an (SP, FP) pair is + // hard since it's easy to misinterpret inter-frame stack + // pointers as base-of-frame pointers; we also don't know the + // sizes of C1 frames (not registered in the nmethod) so can't + // derive them from SP. + + setValues(sp, fp, pc); + return true; + } else { + if (vm.getInterpreter().contains(pc)) { + if (DEBUG) { + System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + + sp + ", fp = " + fp + ", pc = " + pc); + } + setValues(sp, fp, pc); + return true; + } + + // For the server compiler, FP is not guaranteed to be valid + // for compiled code. In addition, an earlier attempt at a + // non-searching algorithm (see below) failed because the + // stack pointer from the thread context was pointing + // (considerably) beyond the ostensible end of the stack, into + // garbage; walking from the topmost frame back caused a crash. + // + // This algorithm takes the current PC as a given and tries to + // find the correct corresponding SP by walking up the stack + // and repeatedly performing stackwalks (very inefficient). + // + // FIXME: there is something wrong with stackwalking across + // adapter frames...this is likely to be the root cause of the + // failure with the simpler algorithm below. + + for (long offset = 0; + offset < regionInBytesToSearch; + offset += vm.getAddressSize()) { + try { + Address curSP = sp.addOffsetTo(offset); + Frame frame = new RISCV64Frame(curSP, null, pc); + RegisterMap map = thread.newRegisterMap(false); + while (frame != null) { + if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { + // We were able to traverse all the way to the + // bottommost Java frame. + // This sp looks good. Keep it. + if (DEBUG) { + System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); + } + setValues(curSP, null, pc); + return true; + } + frame = frame.sender(map); + } + } catch (Exception e) { + if (DEBUG) { + System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); + } + // Bad SP. Try another. + } + } + + // Were not able to find a plausible SP to go with this PC. + // Bail out. + return false; + } + } else { + // If the current program counter was not known to us as a Java + // PC, we currently assume that we are in the run-time system + // and attempt to look to thread-local storage for saved SP and + // FP. Note that if these are null (because we were, in fact, + // in Java code, i.e., vtable stubs or similar, and the SA + // didn't have enough insight into the target VM to understand + // that) then we are going to lose the entire stack trace for + // the thread, which is sub-optimal. FIXME. + + if (DEBUG) { + System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + + thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); + } + if (thread.getLastJavaSP() == null) { + return false; // No known Java frames on stack + } + + // The runtime has a nasty habit of not saving fp in the frame + // anchor, leaving us to grovel about in the stack to find a + // plausible address. Fortunately, this only happens in + // compiled code; there we always have a valid PC, and we always + // push LR and FP onto the stack as a pair, with FP at the lower + // address. + pc = thread.getLastJavaPC(); + fp = thread.getLastJavaFP(); + sp = thread.getLastJavaSP(); + + if (fp == null) { + CodeCache cc = vm.getCodeCache(); + if (cc.contains(pc)) { + CodeBlob cb = cc.findBlob(pc); + if (DEBUG) { + System.out.println("FP is null. Found blob frame size " + cb.getFrameSize()); + } + // See if we can derive a frame pointer from SP and PC + long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize(); + if (link_offset >= 0) { + fp = sp.addOffsetTo(link_offset); + } + } + } + + // We found a PC in the frame anchor. Check that it's plausible, and + // if it is, use it. + if (vm.isJavaPCDbg(pc)) { + setValues(sp, fp, pc); + } else { + setValues(sp, fp, null); + } + + return true; + } + } + + public Address getSP() { return spFound; } + public Address getFP() { return fpFound; } + /** May be null if getting values from thread-local storage; take + care to call the correct RISCV64Frame constructor to recover this if + necessary */ + public Address getPC() { return pcFound; } + + private void setValues(Address sp, Address fp, Address pc) { + spFound = sp; + fpFound = fp; + pcFound = pc; + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java new file mode 100644 index 0000000000000000000000000000000000000000..df280005d7240bb181a451249c10b45ae78ea6e7 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Red Hat Inc. + * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.riscv64; + +import java.util.*; +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.compiler.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.utilities.Observable; +import sun.jvm.hotspot.utilities.Observer; + +/** Specialization of and implementation of abstract methods of the + Frame class for the riscv64 family of CPUs. */ + +public class RISCV64Frame extends Frame { + private static final boolean DEBUG; + static { + DEBUG = System.getProperty("sun.jvm.hotspot.runtime.RISCV64.RISCV64Frame.DEBUG") != null; + } + + // Java frames + private static final int LINK_OFFSET = -2; + private static final int RETURN_ADDR_OFFSET = -1; + private static final int SENDER_SP_OFFSET = 0; + + // Interpreter frames + private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -3; + private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; + private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; + private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only + private static int INTERPRETER_FRAME_PADDING_OFFSET; + private static int INTERPRETER_FRAME_MIRROR_OFFSET; + private static int INTERPRETER_FRAME_CACHE_OFFSET; + private static int INTERPRETER_FRAME_LOCALS_OFFSET; + private static int INTERPRETER_FRAME_BCX_OFFSET; + private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; + private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; + private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; + + // Entry frames + private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -10; + + // Native frames + private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; + + private static VMReg fp = new VMReg(8); + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; + INTERPRETER_FRAME_PADDING_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; + INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_PADDING_OFFSET - 1; + INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1; + INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; + INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; + INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; + INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; + INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; + } + + + // an additional field beyond sp and pc: + Address raw_fp; // frame pointer + private Address raw_unextendedSP; + + private RISCV64Frame() { + } + + private void adjustForDeopt() { + if ( pc != null) { + // Look for a deopt pc and if it is deopted convert to original pc + CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); + if (cb != null && cb.isJavaMethod()) { + NMethod nm = (NMethod) cb; + if (pc.equals(nm.deoptHandlerBegin())) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); + } + // adjust pc if frame is deoptimized. + pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); + deoptimized = true; + } + } + } + } + + public RISCV64Frame(Address raw_sp, Address raw_fp, Address pc) { + this.raw_sp = raw_sp; + this.raw_unextendedSP = raw_sp; + this.raw_fp = raw_fp; + this.pc = pc; + adjustUnextendedSP(); + + // Frame must be fully constructed before this call + adjustForDeopt(); + + if (DEBUG) { + System.out.println("RISCV64Frame(sp, fp, pc): " + this); + dumpStack(); + } + } + + public RISCV64Frame(Address raw_sp, Address raw_fp) { + this.raw_sp = raw_sp; + this.raw_unextendedSP = raw_sp; + this.raw_fp = raw_fp; + + // We cannot assume SP[-1] always contains a valid return PC (e.g. if + // the callee is a C/C++ compiled frame). If the PC is not known to + // Java then this.pc is null. + Address savedPC = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + if (VM.getVM().isJavaPCDbg(savedPC)) { + this.pc = savedPC; + } + + adjustUnextendedSP(); + + // Frame must be fully constructed before this call + adjustForDeopt(); + + if (DEBUG) { + System.out.println("RISCV64Frame(sp, fp): " + this); + dumpStack(); + } + } + + public RISCV64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { + this.raw_sp = raw_sp; + this.raw_unextendedSP = raw_unextendedSp; + this.raw_fp = raw_fp; + this.pc = pc; + adjustUnextendedSP(); + + // Frame must be fully constructed before this call + adjustForDeopt(); + + if (DEBUG) { + System.out.println("RISCV64Frame(sp, unextendedSP, fp, pc): " + this); + dumpStack(); + } + + } + + public Object clone() { + RISCV64Frame frame = new RISCV64Frame(); + frame.raw_sp = raw_sp; + frame.raw_unextendedSP = raw_unextendedSP; + frame.raw_fp = raw_fp; + frame.pc = pc; + frame.deoptimized = deoptimized; + return frame; + } + + public boolean equals(Object arg) { + if (arg == null) { + return false; + } + + if (!(arg instanceof RISCV64Frame)) { + return false; + } + + RISCV64Frame other = (RISCV64Frame) arg; + + return (AddressOps.equal(getSP(), other.getSP()) && + AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && + AddressOps.equal(getFP(), other.getFP()) && + AddressOps.equal(getPC(), other.getPC())); + } + + public int hashCode() { + if (raw_sp == null) { + return 0; + } + + return raw_sp.hashCode(); + } + + public String toString() { + return "sp: " + (getSP() == null? "null" : getSP().toString()) + + ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + + ", fp: " + (getFP() == null? "null" : getFP().toString()) + + ", pc: " + (pc == null? "null" : pc.toString()); + } + + // accessors for the instance variables + public Address getFP() { return raw_fp; } + public Address getSP() { return raw_sp; } + public Address getID() { return raw_sp; } + + // FIXME: not implemented yet + public boolean isSignalHandlerFrameDbg() { return false; } + public int getSignalNumberDbg() { return 0; } + public String getSignalNameDbg() { return null; } + + public boolean isInterpretedFrameValid() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isInterpretedFrame(), "Not an interpreted frame"); + } + + // These are reasonable sanity checks + if (getFP() == null || getFP().andWithMask(0x3) != null) { + return false; + } + + if (getSP() == null || getSP().andWithMask(0x3) != null) { + return false; + } + + if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { + return false; + } + + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (getFP().lessThanOrEqual(getSP())) { + // this attempts to deal with unsigned comparison above + return false; + } + + if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { + // stack frames shouldn't be large. + return false; + } + + return true; + } + + public Frame sender(RegisterMap regMap, CodeBlob cb) { + RISCV64RegisterMap map = (RISCV64RegisterMap) regMap; + + if (Assert.ASSERTS_ENABLED) { + Assert.that(map != null, "map must be set"); + } + + // Default is we done have to follow them. The sender_for_xxx will + // update it accordingly + map.setIncludeArgumentOops(false); + + if (isEntryFrame()) return senderForEntryFrame(map); + if (isInterpretedFrame()) return senderForInterpreterFrame(map); + + if(cb == null) { + cb = VM.getVM().getCodeCache().findBlob(getPC()); + } else { + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); + } + } + + if (cb != null) { + return senderForCompiledFrame(map, cb); + } + + // Must be native-compiled frame, i.e. the marshaling code for native + // methods that exists in the core system. + return new RISCV64Frame(getSenderSP(), getLink(), getSenderPC()); + } + + private Frame senderForEntryFrame(RISCV64RegisterMap map) { + if (DEBUG) { + System.out.println("senderForEntryFrame"); + } + if (Assert.ASSERTS_ENABLED) { + Assert.that(map != null, "map must be set"); + } + // Java frame called from C; skip all C frames and return top C + // frame of that chunk as the sender + RISCV64JavaCallWrapper jcw = (RISCV64JavaCallWrapper) getEntryFrameCallWrapper(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); + Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); + } + RISCV64Frame fr; + if (jcw.getLastJavaPC() != null) { + fr = new RISCV64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); + } else { + fr = new RISCV64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); + } + map.clear(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); + } + return fr; + } + + //------------------------------------------------------------------------------ + // frame::adjust_unextended_sp + private void adjustUnextendedSP() { + // If we are returning to a compiled MethodHandle call site, the + // saved_fp will in fact be a saved value of the unextended SP. The + // simplest way to tell whether we are returning to such a call site + // is as follows: + + CodeBlob cb = cb(); + NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); + if (senderNm != null) { + // If the sender PC is a deoptimization point, get the original + // PC. For MethodHandle call site the unextended_sp is stored in + // saved_fp. + if (senderNm.isDeoptMhEntry(getPC())) { + raw_unextendedSP = getFP(); + } + else if (senderNm.isDeoptEntry(getPC())) { + } + else if (senderNm.isMethodHandleReturn(getPC())) { + raw_unextendedSP = getFP(); + } + } + } + + private Frame senderForInterpreterFrame(RISCV64RegisterMap map) { + if (DEBUG) { + System.out.println("senderForInterpreterFrame"); + } + Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); + Address sp = addressOfStackSlot(SENDER_SP_OFFSET); + // We do not need to update the callee-save register mapping because above + // us is either another interpreter frame or a converter-frame, but never + // directly a compiled frame. + // 11/24/04 SFG. With the removal of adapter frames this is no longer true. + // However c2 no longer uses callee save register for java calls so there + // are no callee register to find. + + if (map.getUpdateMap()) + updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); + + return new RISCV64Frame(sp, unextendedSP, getLink(), getSenderPC()); + } + + private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { + map.setLocation(fp, savedFPAddr); + } + + private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) { + if (DEBUG) { + System.out.println("senderForCompiledFrame"); + } + + // + // NOTE: some of this code is (unfortunately) duplicated RISCV64CurrentFrameGuess + // + + if (Assert.ASSERTS_ENABLED) { + Assert.that(map != null, "map must be set"); + } + + // frame owned by optimizing compiler + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); + } + Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); + + // The return_address is always the word on the stack + Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); + + // This is the saved value of FP which may or may not really be an FP. + // It is only an FP if the sender is an interpreter frame. + Address savedFPAddr = senderSP.addOffsetTo(-2 * VM.getVM().getAddressSize()); + + if (map.getUpdateMap()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. + map.setIncludeArgumentOops(cb.callerMustGCArguments()); + + if (cb.getOopMaps() != null) { + ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); + } + + // Since the prolog does the save and restore of FP there is no oopmap + // for it so we must fill in its location as if there was an oopmap entry + // since if our caller was compiled code there could be live jvm state in it. + updateMapWithSavedLink(map, savedFPAddr); + } + + return new RISCV64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); + } + + protected boolean hasSenderPD() { + return true; + } + + public long frameSize() { + return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); + } + + public Address getLink() { + try { + if (DEBUG) { + System.out.println("Reading link at " + addressOfStackSlot(LINK_OFFSET) + + " = " + addressOfStackSlot(LINK_OFFSET).getAddressAt(0)); + } + return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); + } catch (Exception e) { + if (DEBUG) + System.out.println("Returning null"); + return null; + } + } + + public Address getUnextendedSP() { return raw_unextendedSP; } + + // Return address: + public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } + public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } + + // return address of param, zero origin index. + public Address getNativeParamAddr(int idx) { + return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); + } + + public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } + + public Address addressOfInterpreterFrameLocals() { + return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); + } + + private Address addressOfInterpreterFrameBCX() { + return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); + } + + public int getInterpreterFrameBCI() { + // FIXME: this is not atomic with respect to GC and is unsuitable + // for use in a non-debugging, or reflective, system. Need to + // figure out how to express this. + Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); + Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); + Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); + return bcpToBci(bcp, method); + } + + public Address addressOfInterpreterFrameMDX() { + return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); + } + + // expression stack + // (the max_stack arguments are used by the GC; see class FrameClosure) + + public Address addressOfInterpreterFrameExpressionStack() { + Address monitorEnd = interpreterFrameMonitorEnd().address(); + return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); + } + + public int getInterpreterFrameExpressionStackDirection() { return -1; } + + // top of expression stack + public Address addressOfInterpreterFrameTOS() { + return getSP(); + } + + /** Expression stack from top down */ + public Address addressOfInterpreterFrameTOSAt(int slot) { + return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); + } + + public Address getInterpreterFrameSenderSP() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isInterpretedFrame(), "interpreted frame expected"); + } + return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); + } + + // Monitors + public BasicObjectLock interpreterFrameMonitorBegin() { + return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); + } + + public BasicObjectLock interpreterFrameMonitorEnd() { + Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); + if (Assert.ASSERTS_ENABLED) { + // make sure the pointer points inside the frame + Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); + Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); + } + return new BasicObjectLock(result); + } + + public int interpreterFrameMonitorSize() { + return BasicObjectLock.size(); + } + + // Method + public Address addressOfInterpreterFrameMethod() { + return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); + } + + // Constant pool cache + public Address addressOfInterpreterFrameCPCache() { + return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); + } + + // Entry frames + public JavaCallWrapper getEntryFrameCallWrapper() { + return new RISCV64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); + } + + protected Address addressOfSavedOopResult() { + // offset is 2 for compiler2 and 3 for compiler1 + return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * + VM.getVM().getAddressSize()); + } + + protected Address addressOfSavedReceiver() { + return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); + } + + private void dumpStack() { + for (Address addr = getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); + AddressOps.lt(addr, getSP()); + addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { + System.out.println(addr + ": " + addr.getAddressAt(0)); + } + System.out.println("-----------------------"); + for (Address addr = getSP(); + AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); + addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { + System.out.println(addr + ": " + addr.getAddressAt(0)); + } + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..d0ad2b559a63c1711687d8de80002cb3b8c5d91f --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.riscv64; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.utilities.Observable; +import sun.jvm.hotspot.utilities.Observer; + +public class RISCV64JavaCallWrapper extends JavaCallWrapper { + private static AddressField lastJavaFPField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("JavaFrameAnchor"); + + lastJavaFPField = type.getAddressField("_last_Java_fp"); + } + + public RISCV64JavaCallWrapper(Address addr) { + super(addr); + } + + public Address getLastJavaFP() { + return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset())); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java new file mode 100644 index 0000000000000000000000000000000000000000..4aeb1c6f557c48f017cb4e61bb4ee635ba14c168 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.riscv64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; + +public class RISCV64RegisterMap extends RegisterMap { + + /** This is the only public constructor */ + public RISCV64RegisterMap(JavaThread thread, boolean updateMap) { + super(thread, updateMap); + } + + protected RISCV64RegisterMap(RegisterMap map) { + super(map); + } + + public Object clone() { + RISCV64RegisterMap retval = new RISCV64RegisterMap(this); + return retval; + } + + // no PD state to clear or copy: + protected void clearPD() {} + protected void initializePD() {} + protected void initializeFromPD(RegisterMap map) {} + protected Address getLocationPD(VMReg reg) { return null; } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInCodeCachePanel.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInCodeCachePanel.java index 21619b1f5ae88f14c6ec7a19ada77eb7133db0bf..c83d791265034db73916701412de9ed60ecac349 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInCodeCachePanel.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInCodeCachePanel.java @@ -79,7 +79,7 @@ public class FindInCodeCachePanel extends SAPanel { } begin = begin.addOffsetTo(addressSize); } - iterated = end.minus(base);; + iterated = end.minus(base); updateProgressBar(null); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java index ced929dea16d48592ee7e752d38716e2b885df0c..c9808063ad3061cc5f97e639f4bb3ec83f6bf87b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java @@ -195,7 +195,7 @@ public class FindInHeapPanel extends JPanel { for (String update : updates) { textArea.append(update); } - updates = new ArrayList<>();; + updates = new ArrayList<>(); } pendingUpdate = false; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java index 76522a6676c19f63bf3107d38c94eced6fb085ad..d1058978eee09da2e7a28ec2832ae24571a48221 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java @@ -31,12 +31,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.math.*; -import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.ui.*; import sun.jvm.hotspot.utilities.PointerFinder; import sun.jvm.hotspot.utilities.PointerLocation; @@ -219,8 +217,7 @@ public class MemoryPanel extends JPanel { String str = (String)t.getTransferData(DataFlavor.stringFlavor); handleImport(c, str); return true; - } catch (UnsupportedFlavorException ufe) { - } catch (IOException ioe) { + } catch (UnsupportedFlavorException | IOException e) { } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/CTypeTreeNodeAdapter.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/CTypeTreeNodeAdapter.java index 42157bcae7ca51366838077290cb5efc6d3f2fbc..114912593ee3ebcd4f08adcc68a8d8108ae9d06a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/CTypeTreeNodeAdapter.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/CTypeTreeNodeAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,11 +132,7 @@ public class CTypeTreeNodeAdapter extends FieldTreeNodeAdapter { try { Oop oop = VM.getVM().getObjectHeap().newOop(handle); return new OopTreeNodeAdapter(oop, cf, getTreeTableMode()); - } catch (AddressException e) { - return new BadAddressTreeNodeAdapter(handle, - new CTypeFieldIdentifier(type, f), - getTreeTableMode()); - } catch (UnknownOopException e) { + } catch (AddressException | UnknownOopException e) { return new BadAddressTreeNodeAdapter(handle, new CTypeFieldIdentifier(type, f), getTreeTableMode()); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/MetadataTreeNodeAdapter.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/MetadataTreeNodeAdapter.java index ba60d08429bef9e903439c97057210795308c8a1..4a5ae3afe9f2f192c15599060cb20d1fee28c030 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/MetadataTreeNodeAdapter.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/MetadataTreeNodeAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -153,9 +153,7 @@ public class MetadataTreeNodeAdapter extends FieldTreeNodeAdapter { if (curField == index) { try { child = new MetadataTreeNodeAdapter(field.getValue(getObj()), field.getID(), getTreeTableMode()); - } catch (AddressException e) { - child = new BadAddressTreeNodeAdapter(getObj().getAddress().getAddressAt(field.getOffset()), field, getTreeTableMode()); - } catch (UnknownOopException e) { + } catch (AddressException | UnknownOopException e) { child = new BadAddressTreeNodeAdapter(getObj().getAddress().getAddressAt(field.getOffset()), field, getTreeTableMode()); } } @@ -166,9 +164,7 @@ public class MetadataTreeNodeAdapter extends FieldTreeNodeAdapter { if (curField == index) { try { child = new OopTreeNodeAdapter(field.getValue(getObj()), field.getID(), getTreeTableMode()); - } catch (AddressException e) { - child = new BadAddressTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field, getTreeTableMode()); - } catch (UnknownOopException e) { + } catch (AddressException | UnknownOopException e) { child = new BadAddressTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field, getTreeTableMode()); } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java index c1c7fa18beee7bd27ee31283882c81c2b460ae17..3146ffa6636c52ad7e32a20001f1042fed51a657 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, 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 @@ -160,9 +160,7 @@ public class OopTreeNodeAdapter extends FieldTreeNodeAdapter { if (curField == index) { try { child = new MetadataTreeNodeAdapter(field.getValue(getObj()), field.getID(), getTreeTableMode()); - } catch (AddressException e) { - child = new BadAddressTreeNodeAdapter(getObj().getHandle().getAddressAt(field.getOffset()), field, getTreeTableMode()); - } catch (UnknownOopException e) { + } catch (AddressException | UnknownOopException e) { child = new BadAddressTreeNodeAdapter(getObj().getHandle().getAddressAt(field.getOffset()), field, getTreeTableMode()); } } @@ -173,9 +171,7 @@ public class OopTreeNodeAdapter extends FieldTreeNodeAdapter { if (curField == index) { try { child = new OopTreeNodeAdapter(field.getValue(getObj()), field.getID(), getTreeTableMode()); - } catch (AddressException e) { - child = new BadAddressTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field, getTreeTableMode()); - } catch (UnknownOopException e) { + } catch (AddressException | UnknownOopException e) { child = new BadAddressTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field, getTreeTableMode()); } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java index 3e66e24700b94e3a85cf8b2480e3d06c55cfe4a2..f4cd4873207a4bbbdf3aa01139fafe8fb6238fbe 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java @@ -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 @@ -50,7 +50,7 @@ public class PlatformInfo { public static boolean knownCPU(String cpu) { final String[] KNOWN = - new String[] {"i386", "x86", "x86_64", "amd64", "ppc64", "ppc64le", "aarch64"}; + new String[] {"i386", "x86", "x86_64", "amd64", "ppc64", "ppc64le", "aarch64", "riscv64"}; for(String s : KNOWN) { if(s.equals(cpu)) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java index cd9e8264f28b5c23994fa3a4a9ecaee01fe7355f..f0e7b0997e9f1088cbffe7d140b76f60624e729f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java @@ -87,6 +87,7 @@ public class PointerFinder { if (heap instanceof GenCollectedHeap) { GenCollectedHeap genheap = (GenCollectedHeap) heap; if (genheap.isIn(a)) { + loc.heap = heap; for (int i = 0; i < genheap.nGens(); i++) { Generation g = genheap.getGen(i); if (g.isIn(a)) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java index a7cfa5de983cc74d5fe855a233f8a4de9fab41f6..d474469c56261c34bcc5398689c5c5b70bd26cca 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java @@ -107,22 +107,21 @@ public class PointerLocation { } public boolean isInHeap() { - return (heap != null || (gen != null)); + return (heap != null); } public boolean isInNewGen() { - return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(0))); + return ((gen != null) && (gen.equals(((GenCollectedHeap)heap).getGen(0)))); } public boolean isInOldGen() { - return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(1))); + return ((gen != null) && (gen.equals(((GenCollectedHeap)heap).getGen(1)))); } public boolean inOtherGen() { return (!isInNewGen() && !isInOldGen()); } - /** Only valid if isInHeap() */ public Generation getGeneration() { return gen; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java index 34e67140b58a490c2c0961a57a7306419b02f819..ec9a9554b14c7b19917fc45d2efac0bd36895ced 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.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 @@ -32,7 +32,6 @@ import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; /** For a set of known roots, descends recursively into the object graph, for each object recording those objects (and their fields) @@ -259,9 +258,6 @@ public class ReversePtrsAnalysis { } } catch (EmptyStackException e) { // Done - } catch (NullPointerException e) { - System.err.println("ReversePtrs: WARNING: " + e + - " during traversal"); } catch (Exception e) { System.err.println("ReversePtrs: WARNING: " + e + " during traversal"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java index 1b7d4c74c27305fc4ef8e719881ca82e910afc2b..3f701b8d24e49052ae8baced63b9c0a9a607eb83 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java @@ -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 @@ -24,15 +24,10 @@ package sun.jvm.hotspot.utilities; -import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.Metadata; -import sun.jvm.hotspot.oops.Klass; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; /** This class determines to the best of its ability, and in a reasonably robust fashion, whether a given pointer is an intact @@ -77,9 +72,7 @@ public class RobustOopDeterminator { Metadata.instantiateWrapperFor(klassField.getValue(oop)); } return true; - } catch (AddressException e) { - return false; - } catch (WrongTypeException e) { + } catch (AddressException | WrongTypeException e) { return false; } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_de.properties b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..e72f53703695a03d71bf719f8e4095f3de39f012 --- /dev/null +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_de.properties @@ -0,0 +1,54 @@ +# +# 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. 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. +# + +usage.java=Verwendung: java -m jdk.httpserver [-b bind address] [-p port] [-d directory]\n [-o none|info|verbose] [-h zum Anzeigen von Optionen]\n [-version zum Anzeigen der Versionsinformationen] + +usage.jwebserver=Verwendung: jwebserver [-b bind address] [-p port] [-d directory]\n [-o none|info|verbose] [-h zum Anzeigen von Optionen]\n [-version zum Anzeigen von Versionsinformationen] + +version={0} {1} + +options=Optionen:\n-b, --bind-address - Adresse, an die das Binding erfolgt. Standard: {0} (Loopback).\n Verwenden Sie f\u00FCr alle Schnittstellen "-b 0.0.0.0" oder "-b ::".\n-d, --directory - Zu bedienendes Verzeichnis. Standard: Aktuelles Verzeichnis.\n-o, --output - Ausgabeformat. none|info|verbose. Standard: info.\n-p, --port - Port, auf dem gehorcht wird. Standard: 8000.\n-h, -?, --help - Gibt diese Hilfemeldung aus und beendet.\n-version, --version - Gibt Versionsinformationen aus und beendet.\nDr\u00FCcken Sie zum Stoppen des Servers Strg+C. + +opt.bindaddress=-b, --bind-address - Adresse, an die das Binding erfolgt. Standard: {0} (Loopback).\n Verwenden Sie f\u00FCr alle Schnittstellen "-b 0.0.0.0" oder "-b ::". +opt.directory=-d, --directory - Zu bedienendes Verzeichnis. Standard: Aktuelles Verzeichnis. +opt.output=-o, --output - Ausgabeformat. none|info|verbose. Standard: info. +opt.port=-p, --port - Port, auf dem gehorcht wird. Standard: 8000. + +loopback.info=Binding an Loopback als Standard. Verwenden Sie f\u00FCr alle Schnittstellen "-b 0.0.0.0" oder "-b ::". + +msg.start.anylocal=Bedient {0} und Unterverzeichnisse auf 0.0.0.0 (alle Schnittstellen) Port {2}\nURL http://{1}:{2}/ + +msg.start.other=Bedient {0} und Unterverzeichnisse auf {1} Port {2}\nURL http://{1}:{2}/ + +error.prefix=Fehler: + +err.unknown.option=unbekannte Option: {0} +err.missing.arg=kein Wert angegeben f\u00FCr {0} +err.invalid.arg=ung\u00FCltiger Wert angegeben f\u00FCr {0}: {1} +err.server.config.failed=Serverkonfiguration nicht erfolgreich: {0} +err.server.handle.failed=Handling des Serveraustauschs nicht erfolgreich: {0} + +html.dir.list=Verzeichnisliste f\u00FCr +html.not.found=Datei wurde nicht gefunden diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_ja.properties b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_ja.properties new file mode 100644 index 0000000000000000000000000000000000000000..974707493a591a458a231e526468cf5a0588acbf --- /dev/null +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_ja.properties @@ -0,0 +1,54 @@ +# +# 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. 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. +# + +usage.java=\u4F7F\u7528\u65B9\u6CD5: java -m jdk.httpserver [-b bind address] [-p port] [-d directory]\n [-o none|info|verbose] [-h to show options]\n [-version to show version information] + +usage.jwebserver=\u4F7F\u7528\u65B9\u6CD5: jwebserver [-b bind address] [-p port] [-d directory]\n [-o none|info|verbose] [-h to show options]\n [-version to show version information] + +version={0} {1} + +options=\u30AA\u30D7\u30B7\u30E7\u30F3:\n-b, --bind-address - \u30D0\u30A4\u30F3\u30C9\u5148\u30A2\u30C9\u30EC\u30B9\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: {0} (\u30EB\u30FC\u30D7\u30D0\u30C3\u30AF)\u3002\n \u3059\u3079\u3066\u306E\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067"-b 0.0.0.0"\u307E\u305F\u306F"-b ::"\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\n-d, --directory - \u4F7F\u7528\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: \u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002\n-o, --output - \u51FA\u529B\u5F62\u5F0F\u3002none|info|verbose\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: info\u3002\n-p, --port - \u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u30DD\u30FC\u30C8\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: 8000\u3002\n-h, -?, --help - \u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\u3002\n-version, --version - \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\u3002\n\u30B5\u30FC\u30D0\u30FC\u3092\u505C\u6B62\u3059\u308B\u306B\u306F\u3001[Ctrl]+[C]\u3092\u62BC\u3057\u307E\u3059\u3002 + +opt.bindaddress=-b, --bind-address - \u30D0\u30A4\u30F3\u30C9\u5148\u30A2\u30C9\u30EC\u30B9\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: {0} (\u30EB\u30FC\u30D7\u30D0\u30C3\u30AF).\n \u3059\u3079\u3066\u306E\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067"-b 0.0.0.0"\u307E\u305F\u306F"-b ::"\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 +opt.directory=-d, --directory - \u4F7F\u7528\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: \u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002 +opt.output=-o, --output - \u51FA\u529B\u5F62\u5F0F\u3002none|info|verbose. \u30C7\u30D5\u30A9\u30EB\u30C8: info\u3002 +opt.port=-p, --port - \u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u30DD\u30FC\u30C8\u3002\u30C7\u30D5\u30A9\u30EB\u30C8: 8000\u3002 + +loopback.info=\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u30EB\u30FC\u30D7\u30D0\u30C3\u30AF\u306B\u30D0\u30A4\u30F3\u30C9\u3057\u307E\u3059\u3002\u3059\u3079\u3066\u306E\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067"-b 0.0.0.0"\u307E\u305F\u306F"-b ::"\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 + +msg.start.anylocal={0}\u304A\u3088\u3073\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30920.0.0.0 (\u3059\u3079\u3066\u306E\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9)\u30DD\u30FC\u30C8{2}\u3067\u4F7F\u7528\u3057\u307E\u3059\nURL http://{1}:{2}/ + +msg.start.other={0}\u304A\u3088\u3073\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092{1}\u30DD\u30FC\u30C8{2}\u3067\u4F7F\u7528\u3057\u307E\u3059\nURL http://{1}:{2}/ + +error.prefix=\u30A8\u30E9\u30FC: + +err.unknown.option=\u4E0D\u660E\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0} +err.missing.arg={0}\u306B\u5024\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 +err.invalid.arg={0}\u306B\u7121\u52B9\u306A\u5024\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F: {1} +err.server.config.failed=\u30B5\u30FC\u30D0\u30FC\u306E\u69CB\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {0} +err.server.handle.failed=\u30B5\u30FC\u30D0\u30FC\u4EA4\u63DB\u51E6\u7406\u304C\u5931\u6557\u3057\u307E\u3057\u305F: {0} + +html.dir.list=\u6B21\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30EA\u30B9\u30C8 +html.not.found=\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_zh_CN.properties b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_zh_CN.properties new file mode 100644 index 0000000000000000000000000000000000000000..1d35a7ecd1b8eeede638016b8ce80f5858632879 --- /dev/null +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver_zh_CN.properties @@ -0,0 +1,54 @@ +# +# 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. 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. +# + +usage.java=\u7528\u6CD5\uFF1Ajava -m jdk.httpserver [-b \u7ED1\u5B9A\u5730\u5740] [-p \u7AEF\u53E3] [-d \u76EE\u5F55]\n [-o none|info|verbose] [-h \u663E\u793A\u9009\u9879]\n [-version \u663E\u793A\u7248\u672C\u4FE1\u606F] + +usage.jwebserver=\u7528\u6CD5\uFF1Ajwebserver [-b \u7ED1\u5B9A\u5730\u5740] [-p \u7AEF\u53E3] [-d \u76EE\u5F55]\n [-o none|info|verbose] [-h \u663E\u793A\u9009\u9879]\n [-version \u663E\u793A\u7248\u672C\u4FE1\u606F] + +version={0} {1} + +options=\u9009\u9879\uFF1A\n-b, --bind-address - \u8981\u7ED1\u5B9A\u5230\u7684\u5730\u5740\u3002\u9ED8\u8BA4\u503C\uFF1A{0}\uFF08\u73AF\u56DE\uFF09\u3002\n \u5982\u679C\u8981\u8868\u793A\u6240\u6709\u63A5\u53E3\uFF0C\u8BF7\u4F7F\u7528 "-b 0.0.0.0" \u6216 "-b ::"\u3002\n-d, --directory - \u8981\u4E3A\u5176\u63D0\u4F9B\u670D\u52A1\u7684\u76EE\u5F55\u3002\u9ED8\u8BA4\u503C\uFF1A\u5F53\u524D\u76EE\u5F55\u3002\n-o, --output - \u8F93\u51FA\u683C\u5F0F\u3002none|info|verbose\u3002\u9ED8\u8BA4\u503C\uFF1Ainfo\u3002\n-p, --port - \u8981\u76D1\u542C\u7684\u7AEF\u53E3\u3002\u9ED8\u8BA4\u503C\uFF1A8000\u3002\n-h, -?, --help - \u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F\u5E76\u9000\u51FA\u3002\n-version, --version - \u8F93\u51FA\u7248\u672C\u4FE1\u606F\u5E76\u9000\u51FA\u3002\n\u8981\u505C\u6B62\u670D\u52A1\u5668\uFF0C\u8BF7\u6309 Ctrl + C\u3002 + +opt.bindaddress=-b, --bind-address - \u8981\u7ED1\u5B9A\u5230\u7684\u5730\u5740\u3002\u9ED8\u8BA4\u503C\uFF1A{0}\uFF08\u73AF\u56DE\uFF09\u3002\n \u5982\u679C\u8981\u8868\u793A\u6240\u6709\u63A5\u53E3\uFF0C\u8BF7\u4F7F\u7528 "-b 0.0.0.0" \u6216 "-b ::"\u3002 +opt.directory=-d, --directory - \u8981\u4E3A\u5176\u63D0\u4F9B\u670D\u52A1\u7684\u76EE\u5F55\u3002\u9ED8\u8BA4\u503C\uFF1A\u5F53\u524D\u76EE\u5F55\u3002 +opt.output=-o, --output - \u8F93\u51FA\u683C\u5F0F\u3002none|info|verbose\u3002\u9ED8\u8BA4\u503C\uFF1Ainfo\u3002 +opt.port=-p, --port - \u8981\u76D1\u542C\u7684\u7AEF\u53E3\u3002\u9ED8\u8BA4\u503C\uFF1A8000\u3002 + +loopback.info=\u9ED8\u8BA4\u60C5\u51B5\u4E0B\u7ED1\u5B9A\u5230\u73AF\u56DE\u3002\u5982\u679C\u8981\u8868\u793A\u6240\u6709\u63A5\u53E3\uFF0C\u8BF7\u4F7F\u7528 "-b 0.0.0.0" \u6216 "-b ::"\u3002 + +msg.start.anylocal=\u4E3A 0.0.0.0\uFF08\u6240\u6709\u63A5\u53E3\uFF09\u7AEF\u53E3 {2} \u4E0A\u7684 {0} \u53CA\u5B50\u76EE\u5F55\u63D0\u4F9B\u670D\u52A1\nURL http://{1}:{2}/ + +msg.start.other=\u4E3A {1} \u7AEF\u53E3 {2} \u4E0A\u7684 {0} \u53CA\u5B50\u76EE\u5F55\u63D0\u4F9B\u670D\u52A1\nURL http://{1}:{2}/ + +error.prefix=\u9519\u8BEF: + +err.unknown.option=\u672A\u77E5\u9009\u9879: {0} +err.missing.arg=\u6CA1\u6709\u4E3A{0}\u6307\u5B9A\u503C +err.invalid.arg=\u4E3A {0} \u63D0\u4F9B\u7684\u503C\u65E0\u6548\uFF1A{1} +err.server.config.failed=\u670D\u52A1\u5668\u914D\u7F6E\u5931\u8D25\uFF1A{0} +err.server.handle.failed=\u670D\u52A1\u5668\u4EA4\u6362\u5904\u7406\u5931\u8D25\uFF1A{0} + +html.dir.list=\u4EE5\u4E0B\u9879\u7684\u76EE\u5F55\u5217\u8868 +html.not.found=\u627E\u4E0D\u5230\u6587\u4EF6 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java index e4fae8e0acfff259fe909123465055a6ca354adf..86627f9f33da0ebc307edebf70189ae2f5aa2260 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.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 Byte128Vector extends ByteVector { return super.testTemplate(Byte128Mask.class, op); // specialize } + @Override + @ForceInline + public final Byte128Mask test(Test op, VectorMask m) { + return super.testTemplate(Byte128Mask.class, op, (Byte128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java index 7c123c893b4e8f8f8da0c3fbda772cc747621d57..f5f9977db082dc66634745985578284b0d4decb1 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.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 Byte256Vector extends ByteVector { return super.testTemplate(Byte256Mask.class, op); // specialize } + @Override + @ForceInline + public final Byte256Mask test(Test op, VectorMask m) { + return super.testTemplate(Byte256Mask.class, op, (Byte256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java index 1b63838b14c8b2f57a0c397f0e1f495f133b4f84..e72dbed51dc5867482812fdc0f8303ad0840dc61 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.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 Byte512Vector extends ByteVector { return super.testTemplate(Byte512Mask.class, op); // specialize } + @Override + @ForceInline + public final Byte512Mask test(Test op, VectorMask m) { + return super.testTemplate(Byte512Mask.class, op, (Byte512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java index 16010b7de0987ac2b4cab568a6b46e64cf7abfe5..c5e060b8de926cd693ce72b0213e73491f67171e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.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 Byte64Vector extends ByteVector { return super.testTemplate(Byte64Mask.class, op); // specialize } + @Override + @ForceInline + public final Byte64Mask test(Test op, VectorMask m) { + return super.testTemplate(Byte64Mask.class, op, (Byte64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java index fb36dab860ce21400f499e0e861cf59a21bb9cf8..5239cd33ea0c999bac66487eb27aa17b22ab49d9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.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 ByteMaxVector extends ByteVector { return super.testTemplate(ByteMaxMask.class, op); // specialize } + @Override + @ForceInline + public final ByteMaxMask test(Test op, VectorMask m) { + return super.testTemplate(ByteMaxMask.class, op, (ByteMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index d67f86f7985bc04a73f6441e584a8344212a001f..e878f938c392a02fe13f15c9f311da2c93855aab 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.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 @@ -573,9 +573,6 @@ public abstract class ByteVector extends AbstractVector { } if (op == NOT) { return broadcast(-1).lanewise(XOR, this); - } else if (op == NEG) { - // FIXME: Support this in the JIT. - return broadcast(0).lanewise(SUB, this); } } int opc = opCode(op); @@ -604,8 +601,6 @@ public abstract class ByteVector extends AbstractVector { } if (op == NOT) { return lanewise(XOR, broadcast(-1), m); - } else if (op == NEG) { - return lanewise(NOT, m).lanewise(ADD, broadcast(1), m); } } int opc = opCode(op); @@ -1855,12 +1850,11 @@ public abstract class ByteVector extends AbstractVector { M testTemplate(Class maskType, Test op) { ByteSpecies vsp = vspecies(); if (opKind(op, VO_SPECIAL)) { - ByteVector bits = this.viewAsIntegralLanes(); VectorMask m; if (op == IS_DEFAULT) { - m = bits.compare(EQ, (byte) 0); + m = compare(EQ, (byte) 0); } else if (op == IS_NEGATIVE) { - m = bits.compare(LT, (byte) 0); + m = compare(LT, (byte) 0); } else { throw new AssertionError(op); @@ -1875,11 +1869,31 @@ public abstract class ByteVector 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) { + 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 +4331,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..c1d2f41857448992faec1fd2b377241dcf2aa384 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 @@ -573,9 +573,6 @@ public abstract class IntVector extends AbstractVector { } if (op == NOT) { return broadcast(-1).lanewise(XOR, this); - } else if (op == NEG) { - // FIXME: Support this in the JIT. - return broadcast(0).lanewise(SUB, this); } } int opc = opCode(op); @@ -604,8 +601,6 @@ public abstract class IntVector extends AbstractVector { } if (op == NOT) { return lanewise(XOR, broadcast(-1), m); - } else if (op == NEG) { - return lanewise(NOT, m).lanewise(ADD, broadcast(1), m); } } int opc = opCode(op); @@ -1854,12 +1849,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 +1868,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 +4056,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..60821caa6bd950ad682526abe289058756e8fa0d 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 @@ -531,9 +531,6 @@ public abstract class LongVector extends AbstractVector { } if (op == NOT) { return broadcast(-1).lanewise(XOR, this); - } else if (op == NEG) { - // FIXME: Support this in the JIT. - return broadcast(0).lanewise(SUB, this); } } int opc = opCode(op); @@ -562,8 +559,6 @@ public abstract class LongVector extends AbstractVector { } if (op == NOT) { return lanewise(XOR, broadcast(-1), m); - } else if (op == NEG) { - return lanewise(NOT, m).lanewise(ADD, broadcast(1), m); } } int opc = opCode(op); @@ -1767,12 +1762,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 +1781,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 +3982,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..7558fc6c56a11defbe75a0de6d79f3803ab78e81 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 @@ -573,9 +573,6 @@ public abstract class ShortVector extends AbstractVector { } if (op == NOT) { return broadcast(-1).lanewise(XOR, this); - } else if (op == NEG) { - // FIXME: Support this in the JIT. - return broadcast(0).lanewise(SUB, this); } } int opc = opCode(op); @@ -604,8 +601,6 @@ public abstract class ShortVector extends AbstractVector { } if (op == NOT) { return lanewise(XOR, broadcast(-1), m); - } else if (op == NEG) { - return lanewise(NOT, m).lanewise(ADD, broadcast(1), m); } } int opc = opCode(op); @@ -1855,12 +1850,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 +1869,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 +4325,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..464cb2853df754a56b72c7b2e8aeee0fe977e99e 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 @@ -596,9 +596,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { #if[BITWISE] if (op == NOT) { return broadcast(-1).lanewise(XOR, this); - } else if (op == NEG) { - // FIXME: Support this in the JIT. - return broadcast(0).lanewise(SUB, this); } #end[BITWISE] } @@ -629,8 +626,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { #if[BITWISE] if (op == NOT) { return lanewise(XOR, broadcast(-1), m); - } else if (op == NEG) { - return lanewise(NOT, m).lanewise(ADD, broadcast(1), m); } #end[BITWISE] } @@ -2128,12 +2123,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 +2153,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 +2163,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 +5538,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.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/jdk/security/jarsigner/JarSigner.java b/src/jdk.jartool/share/classes/jdk/security/jarsigner/JarSigner.java index 08fad553cc9b3defe22121ee957bbda9489c717c..74c687912fe17cc9a09e16017d0a987d10651c0a 100644 --- a/src/jdk.jartool/share/classes/jdk/security/jarsigner/JarSigner.java +++ b/src/jdk.jartool/share/classes/jdk/security/jarsigner/JarSigner.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 @@ -417,29 +417,30 @@ public final class JarSigner { /** * Gets the default digest algorithm. * - * @implNote This implementation returns "SHA-256". The value may + * @implNote This implementation returns "SHA-384". The value may * change in the future. * * @return the default digest algorithm. */ public static String getDefaultDigestAlgorithm() { - return "SHA-256"; + return "SHA-384"; } /** * Gets the default signature algorithm for a private key. - * For example, SHA256withRSA for a 2048-bit RSA key, and + * For example, SHA384withRSA for a 2048-bit RSA key, and * SHA384withECDSA for a 384-bit EC key. * * @implNote This implementation makes use of comparable strengths - * as defined in Tables 2 and 3 of NIST SP 800-57 Part 1-Rev.4. - * Specifically, if a DSA or RSA key with a key size greater than 7680 + * as defined in Tables 2 and 3 of NIST SP 800-57 Part 1-Rev.5 as + * well as NIST recommendations as appropriate. + * Specifically, if an RSA key with a key size greater than 7680 * bits, or an EC key with a key size greater than or equal to 512 bits, * SHA-512 will be used as the hash function for the signature. - * If a DSA or RSA key has a key size greater than 3072 bits, or an - * EC key has a key size greater than or equal to 384 bits, SHA-384 will - * be used. Otherwise, SHA-256 will be used. The value may - * change in the future. + * Otherwise, SHA-384 will be used unless the key size is too small + * for resulting signature algorithm. As for DSA keys, the SHA256withDSA + * signature algorithm is returned regardless of key size. + * The value may change in the future. * * @param key the private key. * @return the default signature algorithm. Returns null if a default 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 750b125f10d8ba6101a09d03e6232d6bef36b2b2..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.*; @@ -1244,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) { @@ -1274,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))); } } @@ -1451,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); @@ -1463,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); + } } } @@ -1516,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); @@ -1526,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); + } } } 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 f5a1bb2e3cba6bad22b5f9156392e2170fa44a53..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 @@ -181,7 +181,9 @@ public class Resources extends java.util.ListResourceBundle { {"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.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java new file mode 100644 index 0000000000000000000000000000000000000000..b66ce1a4deeeb17ef66eb668d67887afe5a97dff --- /dev/null +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2000, 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 sun.security.tools.jarsigner; + +/** + *

    This class represents the ResourceBundle + * for JarSigner. + * + */ +public class Resources_de extends java.util.ListResourceBundle { + + private static final Object[][] contents = { + + // shared (from jarsigner) + {"SPACE", " "}, + {"6SPACE", " "}, + {"COMMA", ", "}, + + {"provclass.not.a.provider", "%s kein Provider"}, + {"provider.name.not.found", "Provider namens \"%s\" nicht gefunden"}, + {"provider.class.not.found", "Provider \"%s\" nicht gefunden"}, + {"jarsigner.error.", "jarsigner-Fehler: "}, + {"Illegal.option.", "Unzul\u00E4ssige Option: "}, + {"This.option.is.forremoval", "Diese Option ist veraltet und wird in einem zuk\u00FCnftigen Release entfernt: "}, + {".keystore.must.be.NONE.if.storetype.is.{0}", + "-keystore muss NONE sein, wenn -storetype {0} ist"}, + {".keypass.can.not.be.specified.if.storetype.is.{0}", + "-keypass kann nicht angegeben werden, wenn -storetype \"{0}\" ist"}, + {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified", + "Wenn -protected angegeben ist, d\u00FCrfen -storepass und -keypass nicht angegeben werden"}, + {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified", + "Wenn der Keystore nicht kennwortgesch\u00FCtzt ist, d\u00FCrfen -storepass und -keypass nicht angegeben werden"}, + {"Usage.jarsigner.options.jar.file.alias", + "Verwendung: jarsigner [options] jar-file alias"}, + {".jarsigner.verify.options.jar.file.alias.", + " jarsigner -verify [options] jar-file [alias...]"}, + {".jarsigner.version", + " jarsigner -version"}, + {".keystore.url.keystore.location", + "[-keystore ] Keystore-Speicherort"}, + {".storepass.password.password.for.keystore.integrity", + "[-storepass ] Kennwort f\u00FCr Keystore-Integrit\u00E4t"}, + {".storetype.type.keystore.type", + "[-storetype ] Keystore-Typ"}, + {".keypass.password.password.for.private.key.if.different.", + "[-keypass ] Kennwort f\u00FCr Private Key (falls unterschiedlich)"}, + {".certchain.file.name.of.alternative.certchain.file", + "[-certchain ] Name der alternativen certchain-Datei"}, + {".sigfile.file.name.of.SF.DSA.file", + "[-sigfile ] Name der SF/DSA-Datei"}, + {".signedjar.file.name.of.signed.JAR.file", + "[-signedjar ] Name der signierten JAR-Datei"}, + {".digestalg.algorithm.name.of.digest.algorithm", + "[-digestalg ] Name des Digestalgorithmus"}, + {".sigalg.algorithm.name.of.signature.algorithm", + "[-sigalg ] Name des Signaturalgorithmus"}, + {".verify.verify.a.signed.JAR.file", + "[-verify] Verifiziert eine signierte JAR-Datei"}, + {".version.print.the.program.version", + "[-version] Gibt die Programmversion aus"}, + {".verbose.suboptions.verbose.output.when.signing.verifying.", + "[-verbose[:suboptions]] Verbose-Ausgabe beim Signieren/Verifizieren."}, + {".suboptions.can.be.all.grouped.or.summary", + " Als Unteroptionen sind \"all\", \"grouped\" und \"summary\" m\u00F6glich"}, + {".certs.display.certificates.when.verbose.and.verifying", + "[-certs] Zeigt Zertifikate bei Verbose und Verifizierung an"}, + {".certs.revocation.check", + "[-revCheck] Aktiviert die Zertifikatswiderrufpr\u00FCfung"}, + {".tsa.url.location.of.the.Timestamping.Authority", + "[-tsa ] Ort der Zeitstempelautorit\u00E4t"}, + {".tsacert.alias.public.key.certificate.for.Timestamping.Authority", + "[-tsacert ] Public-Key-Zertifikat f\u00FCr Zeitstempelautorit\u00E4t"}, + {".tsapolicyid.tsapolicyid.for.Timestamping.Authority", + "[-tsapolicyid ] TSAPolicyID f\u00FCr Zeitstempelautorit\u00E4t"}, + {".tsadigestalg.algorithm.of.digest.data.in.timestamping.request", + "[-tsadigestalg ] Algorithmus der Digestdaten in Zeitstempelanforderung"}, + {".altsigner.class.class.name.of.an.alternative.signing.mechanism", + "[-altsigner ] Klassenname eines alternativen Signiermechanismus\n (Diese Option ist veraltet und wird in einem zuk\u00FCnftigen Release entfernt.)"}, + {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism", + "[-altsignerpath ] Speicherort eines alternativen Signiermechanismus\n (Diese Option ist veraltet und wird in einem zuk\u00FCnftigen Release entfernt.)"}, + {".internalsf.include.the.SF.file.inside.the.signature.block", + "[-internalsf] SF-Datei in Signaturblock aufnehmen"}, + {".sectionsonly.don.t.compute.hash.of.entire.manifest", + "[-sectionsonly] Berechnet nicht den Hash des gesamten Manifests"}, + {".protected.keystore.has.protected.authentication.path", + "[-protected] Keystore hat gesch\u00FCtzten Authentifizierungspfad"}, + {".providerName.name.provider.name", + "[-providerName ] Providername"}, + {".add.provider.option", + "[-addprovider F\u00FCgt einen Sicherheitsprovider nach Name hinzu (z.B. SunPKCS11)"}, + {".providerArg.option.1", + " [-providerArg ]] ... Konfiguriert Argument f\u00FCr -addprovider"}, + {".providerClass.option", + "[-providerClass F\u00FCgt einen Sicherheitsprovider nach vollqualifiziertem Klassennamen hinzu"}, + {".providerArg.option.2", + " [-providerArg ]] ... Konfiguriert Argument f\u00FCr -providerClass"}, + {".strict.treat.warnings.as.errors", + "[-strict] Behandelt Warnungen als Fehler"}, + {".conf.url.specify.a.pre.configured.options.file", + "[-conf ] Vorkonfigurierte Optionsdatei angeben"}, + {".print.this.help.message", + "[-? -h --help] Gibt diese Hilfemeldung aus"}, + {"Option.lacks.argument", "Argument fehlt in Option"}, + {"Please.type.jarsigner.help.for.usage", "Geben Sie jarsigner --help ein, um Verwendungsinformationen anzuzeigen"}, + {"Please.specify.jarfile.name", "Geben Sie den Namen der JAR-Datei an"}, + {"Please.specify.alias.name", "Geben Sie einen Aliasnamen an"}, + {"Only.one.alias.can.be.specified", "Nur ein Alias kann angegeben werden"}, + {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.", + "Diese JAR-Datei enth\u00E4lt signierte Eintr\u00E4ge, die nicht von den angegebenen Aliasnamen signiert wurden."}, + {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.", + "Diese JAR-Datei enth\u00E4lt signierte Eintr\u00E4ge, die nicht vom Alias in diesem Keystore signiert wurden."}, + {"s", "s"}, + {"m", "m"}, + {"k", "k"}, + {"X", "X"}, + {"q", "?"}, + {".and.d.more.", "(und %d mehr)"}, + {".s.signature.was.verified.", + " s = Signatur wurde verifiziert "}, + {".m.entry.is.listed.in.manifest", + " m = Eintrag ist in Manifest aufgef\u00FChrt"}, + {".k.at.least.one.certificate.was.found.in.keystore", + " k = Mindestens ein Zertifikat im Keystore gefunden"}, + {".X.not.signed.by.specified.alias.es.", + " X = Nicht von den angegebenen Aliasnamen signiert"}, + {".q.unsigned.entry", + " ? = Nicht signierter Eintrag"}, + {"no.manifest.", "Kein Manifest."}, + {".Signature.related.entries.","(Signaturbezogene Eintr\u00E4ge)"}, + {".Unsigned.entries.", "(Nicht signierte Eintr\u00E4ge)"}, + {".Directory.entries.", "(Verzeichniseintr\u00E4ge)"}, + {"jar.is.unsigned", + "JAR-Datei ist nicht signiert."}, + {"jar.treated.unsigned", + "Warnung: Signatur kann entweder nicht geparst oder nicht verifiziert werden. Die JAR-Datei wird als nicht signiert behandelt. Weitere Informationen erhalten Sie, indem Sie \"jarsigner\" mit aktiviertem Debugging erneut ausf\u00FChren (-J-Djava.security.debug=jar)."}, + {"jar.treated.unsigned.see.weak", + "Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der jetzt deaktiviert ist.\n\nF\u00FChren Sie \"jarsigner\" mit der Option \"-verbose\" erneut aus, um weitere Einzelheiten zu erhalten."}, + {"jar.treated.unsigned.see.weak.verbose", + "Warnung: Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der mittlerweile von der folgenden Sicherheitseigenschaft deaktiviert wurde:"}, + {"jar.signed.", "JAR-Datei signiert."}, + {"jar.signed.with.signer.errors.", "JAR-Datei signiert, mit Signaturgeberfehlern."}, + {"jar.verified.", "JAR-Datei verifiziert."}, + {"jar.verified.with.signer.errors.", "JAR-Datei verifiziert, mit Signaturgeberfehlern."}, + + {"history.with.ts", "- Von \"%1$s\" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s\n Zeitstempel von \"%6$s\" am %5$tc\n Digestalgorithmus f\u00FCr Zeitstempel: %7$s\n Signaturalgorithmus f\u00FCr Zeitstempel: %8$s, %9$s"}, + {"history.without.ts", "- Von \"%1$s\" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s"}, + {"history.unparsable", "- Signaturbezogene Datei %s kann nicht geparst werden"}, + {"history.nosf", "- Signaturbezogene Datei META-INF/%s.SF fehlt"}, + {"history.nobk", "- Blockdatei f\u00FCr signaturbezogene Datei META-INF/%s.SF fehlt"}, + + {"with.weak", "%s (schwach)"}, + {"with.disabled", "%s (deaktiviert)"}, + {"key.bit", "%d-Bit-Schl\u00FCssel"}, + {"key.bit.weak", "%d-Bit-Schl\u00FCssel (schwach)"}, + {"key.bit.disabled", "%d-Bit-Schl\u00FCssel (deaktiviert)"}, + {"unknown.size", "unbekannte Gr\u00F6\u00DFe"}, + {"extra.attributes.detected", "POSIX-Dateiberechtigung und/oder Symlink-Attribute erkannt. Diese Attribute werden bei der Signatur ignoriert und sind nicht durch die Signatur gesch\u00FCtzt."}, + + {"jarsigner.", "jarsigner: "}, + {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", + "Signaturdateiname muss aus den folgenden Zeichen bestehen: A-Z, 0-9, _ oder -"}, + {"unable.to.open.jar.file.", "JAR-Datei kann nicht ge\u00F6ffnet werden: "}, + {"unable.to.create.", "Erstellen nicht m\u00F6glich: "}, + {".adding.", " Wird hinzugef\u00FCgt: "}, + {".updating.", " Wird aktualisiert: "}, + {".signing.", " Wird signiert: "}, + {"attempt.to.rename.signedJarFile.to.jarFile.failed", + "Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich"}, + {"attempt.to.rename.jarFile.to.origJar.failed", + "Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich"}, + {"unable.to.sign.jar.", "JAR-Datei kann nicht signiert werden: "}, + {"Enter.Passphrase.for.keystore.", "Passphrase f\u00FCr Keystore eingeben: "}, + {"keystore.load.", "Keystore-Ladevorgang: "}, + {"certificate.exception.", "Zertifikatsausnahme: "}, + {"unable.to.instantiate.keystore.class.", + "Keystore-Klasse kann nicht instanziiert werden: "}, + {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and", + "Zertifikatskette nicht gefunden f\u00FCr: {0}. {1} muss einen g\u00FCltigen Keystore-Schl\u00FCssel referenzieren, der einen Private Key und eine zugeh\u00F6rige Public-Key-Zertifikatskette enth\u00E4lt."}, + {"File.specified.by.certchain.does.not.exist", + "Von -certchain angegebene Datei ist nicht vorhanden"}, + {"Cannot.restore.certchain.from.file.specified", + "Zertifikatskette kann nicht aus angegebener Datei wiederhergestellt werden"}, + {"Certificate.chain.not.found.in.the.file.specified.", + "Zertifikatskette nicht in der angegebenen Datei gefunden."}, + {"found.non.X.509.certificate.in.signer.s.chain", + "Nicht-X.509-Zertifikat in Kette des Signaturgebers gefunden"}, + {"Enter.key.password.for.alias.", "Schl\u00FCsselkennwort f\u00FCr {0} eingeben: "}, + {"unable.to.recover.key.from.keystore", + "Schl\u00FCssel kann nicht aus Keystore wiederhergestellt werden"}, + {"key.associated.with.alias.not.a.private.key", + "Mit {0} verkn\u00FCpfter Schl\u00FCssel ist kein Private Key"}, + {"you.must.enter.key.password", "Sie m\u00FCssen ein Schl\u00FCsselkennwort eingeben"}, + {"unable.to.read.password.", "Kennwort kann nicht gelesen werden: "}, + {"certificate.is.valid.from", "Zertifikat ist von {0} bis {1} g\u00FCltig"}, + {"certificate.expired.on", "Zertifikat ist am {0} abgelaufen"}, + {"certificate.is.not.valid.until", + "Zertifikat ist erst ab {0} g\u00FCltig"}, + {"certificate.will.expire.on", "Zertifikat l\u00E4uft am {0} ab"}, + {".Invalid.certificate.chain.", "[Ung\u00FCltige Zertifikatskette: "}, + {".Invalid.TSA.certificate.chain.", "[Ung\u00FCltige TSA-Zertifikatskette: "}, + {"requesting.a.signature.timestamp", + "Signaturzeitstempel wird angefordert"}, + {"TSA.location.", "TSA-Ort: "}, + {"TSA.certificate.", "TSA-Zertifikat: "}, + {"no.response.from.the.Timestamping.Authority.", + "Keine Antwort von der Zeitstempelautorit\u00E4t. Bei Verbindungen hinter einer Firewall muss m\u00F6glicherweise ein HTTP- oder HTTPS-Proxy angegeben werden. Geben Sie die folgenden Optionen f\u00FCr \"jarsigner\" an:"}, + {"or", "oder"}, + {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the", + "Zertifikat nicht gefunden f\u00FCr: {0}. {1} muss einen g\u00FCltigen Keystore-Eintrag referenzieren, der ein X.509-Public-Key-Zertifikat f\u00FCr die Zeitstempelautorit\u00E4t enth\u00E4lt."}, + {"using.an.alternative.signing.mechanism", + "Verwendung eines alternativen Signaturmechanismus"}, + {"entry.was.signed.on", "Eintrag wurde signiert am {0}"}, + {"Warning.", "Warnung: "}, + {"Error.", "Fehler: "}, + {"...Signer", ">>> Signaturgeber"}, + {"...TSA", ">>> TSA"}, + {"trusted.certificate", "vertrauensw\u00FCrdiges Zertifikat"}, + {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", + "Diese JAR-Datei enth\u00E4lt nicht signierte Eintr\u00E4ge, deren Integrit\u00E4t nicht gepr\u00FCft wurde. "}, + {"This.jar.contains.entries.whose.signer.certificate.has.expired.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Signaturgeberzertifikat abgelaufen ist."}, + {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Signaturgeberzertifikat innerhalb der n\u00E4chsten sechs Monate abl\u00E4uft. "}, + {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Signaturgeberzertifikat noch nicht g\u00FCltig ist. "}, + {"This.jar.contains.entries.whose.signer.certificate.is.self.signed.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Signaturgeberzertifikat selbstsigniert ist."}, + {"Re.run.with.the.verbose.and.certs.options.for.more.details.", + "F\u00FChren Sie den Befehl erneut mit den Optionen -verbose und -certs aus, um weitere Details zu erhalten."}, + {"The.signer.certificate.has.expired.", + "Das Signaturgeberzertifikat ist abgelaufen."}, + {"The.timestamp.expired.1.but.usable.2", + "Der Zeitstempel ist am %1$tY-%1$tm-%1$td abgelaufen. Die JAR-Datei bleibt aber g\u00FCltig, bis das Signaturgeberzertifikat am %2$tY-%2$tm-%2$td abl\u00E4uft."}, + {"The.timestamp.has.expired.", + "Der Zeitstempel ist abgelaufen."}, + {"The.signer.certificate.will.expire.within.six.months.", + "Das Signaturgeberzertifikat l\u00E4uft innerhalb der n\u00E4chsten sechs Monate ab."}, + {"The.timestamp.will.expire.within.one.year.on.1", + "Der Zeitstempel l\u00E4uft innerhalb des n\u00E4chsten Jahres am %1$tY-%1$tm-%1$td ab."}, + {"The.timestamp.will.expire.within.one.year.on.1.but.2", + "Der Zeitstempel l\u00E4uft innerhalb des n\u00E4chsten Jahres am %1$tY-%1$tm-%1$td ab. Die JAR-Datei bleibt aber g\u00FCltig, bis das Signaturgeberzertifikat am %2$tY-%2$tm-%2$td abl\u00E4uft."}, + {"The.signer.certificate.is.not.yet.valid.", + "Das Signaturgeberzertifikat ist noch nicht g\u00FCltig."}, + {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.", + "Die KeyUsage-Erweiterung des Signaturgeberzertifikats l\u00E4sst keine Codesignatur zu."}, + {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.", + "Die ExtendedKeyUsage-Erweiterung des Signaturgeberzertifikats l\u00E4sst keine Codesignatur zu."}, + {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.", + "Die NetscapeCertType-Erweiterung des Signaturgeberzertifikats l\u00E4sst keine Codesignatur zu."}, + {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, bei denen die KeyUsage-Erweiterung des Signaturgeberzertifikats keine Codesignatur zul\u00E4sst."}, + {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, bei denen die ExtendedKeyUsage-Erweiterung des Signaturgeberzertifikats keine Codesignatur zul\u00E4sst."}, + {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, bei denen die NetscapeCertType-Erweiterung des Signaturgeberzertifikats keine Codesignatur zul\u00E4sst."}, + {".{0}.extension.does.not.support.code.signing.", + "[{0}-Erweiterung unterst\u00FCtzt keine Codesignatur]"}, + {"The.signer.s.certificate.chain.is.invalid.reason.1", + "Die Zertifikatskette des Signaturgebers ist ung\u00FCltig. Grund: %s"}, + {"The.tsa.certificate.chain.is.invalid.reason.1", + "Die TSA-Zertifikatskette ist ung\u00FCltig. Grund: %s"}, + {"The.signer.s.certificate.is.self.signed.", + "Das Zertifikat des Signaturgebers ist selbstsigniert."}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.", + "Der f\u00FCr die Option %2$s angegebene %1$s-Algorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is.disabled.", + "Der f\u00FCr die Option %2$s angegebene %1$s-Algorithmus gilt als Sicherheitsrisiko und ist deaktiviert."}, + {"The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.", + "Der %1$s-Digestalgorithmus des Zeitstempels gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.", + "Der %1$s-Digestalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.", + "Der %1$s-Signaturalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"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.", + "Der %1$s-Signaturschl\u00FCssel hat eine Schl\u00FCsselgr\u00F6\u00DFe von %2$d. Das gilt als Sicherheitsrisiko. Diese Schl\u00FCsselgr\u00F6\u00DFe wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.", + "Der %1$s-Signaturschl\u00FCssel hat eine Schl\u00FCsselgr\u00F6\u00DFe von %2$d. Das gilt als Sicherheitsrisiko und ist deaktiviert."}, + {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Zertifikatskette ung\u00FCltig ist. Grund: %s"}, + {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", + "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren TSA-Zertifikatskette ung\u00FCltig ist. Grund: %s"}, + {"no.timestamp.signing", + "Weder -tsa noch -tsacert wurde angegeben, und diese JAR-Datei hat keinen Zeitstempel. Ohne Zeitstempel k\u00F6nnen Benutzer diese JAR-Datei nach dem Ablaufdatum des Signaturgeberzertifikats (%1$tY-%1$tm-%1$td) m\u00F6glicherweise nicht mehr validieren."}, + {"invalid.timestamp.signing", + "Der Zeitstempel ist ung\u00FCltig. Ohne einen g\u00FCltigen Zeitstempel k\u00F6nnen Benutzer diese JAR-Datei nach dem Ablaufdatum des Signaturgeberzertifikats (%1$tY-%1$tm-%1$td) m\u00F6glicherweise nicht mehr validieren."}, + {"no.timestamp.verifying", + "Diese JAR-Datei enth\u00E4lt Signaturen ohne Zeitstempel. Ohne einen Zeitstempel k\u00F6nnen Benutzer diese JAR-Datei nach dem Ablauf eines Signaturgeberzertifikats (fr\u00FChestens %1$tY-%1$tm-%1$td) m\u00F6glicherweise nicht mehr validieren."}, + {"bad.timestamp.verifying", + "Diese JAR-Datei enth\u00E4lt Signaturen mit einem ung\u00FCltigen Zeitstempel. Ohne einen g\u00FCltigen Zeitstempel k\u00F6nnen Benutzer diese JAR-Datei nach dem Ablauf eines Signaturgeberzertifikats (fr\u00FChestens %1$tY-%1$tm-%1$td) m\u00F6glicherweise nicht mehr validieren.\nF\u00FChren Sie \"jarsigner\" mit -J-Djava.security.debug=jar erneut aus, um weitere Informationen zu erhalten."}, + {"The.signer.certificate.will.expire.on.1.", + "Das Signaturgeberzertifikat l\u00E4uft am %1$tY-%1$tm-%1$td ab."}, + {"The.timestamp.will.expire.on.1.", + "Der Zeitstempel l\u00E4uft am %1$tY-%1$tm-%1$td ab."}, + {"signer.cert.expired.1.but.timestamp.good.2.", + "Das Signaturgeberzertifikat ist am %1$tY-%1$tm-%1$td abgelaufen. Die JAR-Datei bleibt aber g\u00FCltig, bis der Zeitstempel am %2$tY-%2$tm-%2$td abl\u00E4uft."}, + {"Unknown.password.type.", "Unbekannter Kennworttyp: "}, + {"Cannot.find.environment.variable.", + "Umgebungsvariable kann nicht gefunden werden: "}, + {"Cannot.find.file.", "Datei kann nicht gefunden werden: "}, + {"event.ocsp.check", "Verbindung zu OCSP-Server bei %s wird hergestellt..."}, + {"event.crl.check", "CRL wird von %s heruntergeladen..."}, + }; + + /** + * Returns the contents of this ResourceBundle. + * + *

    + * + * @return the contents of this ResourceBundle. + */ + @Override + public Object[][] getContents() { + return contents; + } +} diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java index 65422c0e68647b79bc1e7b0a93387884ecabfa99..aca0727297ca10c0504e63d6e2c3fd56d065772b 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java @@ -57,6 +57,8 @@ public class Resources_ja extends java.util.ListResourceBundle { "\u4F7F\u7528\u65B9\u6CD5: jarsigner [options] jar-file alias"}, {".jarsigner.verify.options.jar.file.alias.", " jarsigner -verify [options] jar-file [alias...]"}, + {".jarsigner.version", + " jarsigner -version"}, {".keystore.url.keystore.location", "[-keystore ] \u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u4F4D\u7F6E"}, {".storepass.password.password.for.keystore.integrity", @@ -77,6 +79,8 @@ public class Resources_ja extends java.util.ListResourceBundle { "[-sigalg ] \u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u540D\u524D"}, {".verify.verify.a.signed.JAR.file", "[-verify] \u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u8A3C"}, + {".version.print.the.program.version", + "[-version] \u30D7\u30ED\u30B0\u30E9\u30E0\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059"}, {".verbose.suboptions.verbose.output.when.signing.verifying.", "[-verbose[:suboptions]] \u7F72\u540D/\u691C\u8A3C\u6642\u306E\u8A73\u7D30\u51FA\u529B\u3002"}, {".suboptions.can.be.all.grouped.or.summary", @@ -131,6 +135,8 @@ public class Resources_ja extends java.util.ListResourceBundle { {"s", "s"}, {"m", "m"}, {"k", "k"}, + {"X", "X"}, + {"q", "?"}, {".and.d.more.", "(\u4ED6\u306B\u3082%d\u500B)"}, {".s.signature.was.verified.", " s=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F "}, @@ -140,9 +146,12 @@ public class Resources_ja extends java.util.ListResourceBundle { " k=1\u3064\u4EE5\u4E0A\u306E\u8A3C\u660E\u66F8\u304C\u30AD\u30FC\u30B9\u30C8\u30A2\u3067\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"}, {".X.not.signed.by.specified.alias.es.", " X =\u6307\u5B9A\u3057\u305F\u5225\u540D\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093"}, + {".q.unsigned.entry", + " ? = \u7F72\u540D\u306A\u3057\u306E\u30A8\u30F3\u30C8\u30EA"}, {"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"}, {".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"}, {".Unsigned.entries.", "(\u7F72\u540D\u306A\u3057\u306E\u30A8\u30F3\u30C8\u30EA)"}, + {".Directory.entries.", "(\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30A8\u30F3\u30C8\u30EA)"}, {"jar.is.unsigned", "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, {"jar.treated.unsigned", diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java index 0cdd2b96ceea787814959432e7b9989bb6843549..47dacd6a8a5b501b874e38385812140f4e9a1fd9 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java @@ -57,6 +57,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u7528\u6CD5: jarsigner [\u9009\u9879] jar-file \u522B\u540D"}, {".jarsigner.verify.options.jar.file.alias.", " jarsigner -verify [\u9009\u9879] jar-file [\u522B\u540D...]"}, + {".jarsigner.version", + " jarsigner -version"}, {".keystore.url.keystore.location", "[-keystore ] \u5BC6\u94A5\u5E93\u4F4D\u7F6E"}, {".storepass.password.password.for.keystore.integrity", @@ -77,6 +79,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "[-sigalg <\u7B97\u6CD5>] \u7B7E\u540D\u7B97\u6CD5\u7684\u540D\u79F0"}, {".verify.verify.a.signed.JAR.file", "[-verify] \u9A8C\u8BC1\u5DF2\u7B7E\u540D\u7684 JAR \u6587\u4EF6"}, + {".version.print.the.program.version", + "[-version] \u8F93\u51FA\u7A0B\u5E8F\u7248\u672C"}, {".verbose.suboptions.verbose.output.when.signing.verifying.", "[-verbose[:suboptions]] \u7B7E\u540D/\u9A8C\u8BC1\u65F6\u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u3002"}, {".suboptions.can.be.all.grouped.or.summary", @@ -131,6 +135,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"s", "s"}, {"m", "m"}, {"k", "k"}, + {"X", "X"}, + {"q", "?"}, {".and.d.more.", "(%d \u53CA\u4EE5\u4E0A)"}, {".s.signature.was.verified.", " s = \u5DF2\u9A8C\u8BC1\u7B7E\u540D "}, @@ -140,9 +146,12 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { " k = \u5728\u5BC6\u94A5\u5E93\u4E2D\u81F3\u5C11\u627E\u5230\u4E86\u4E00\u4E2A\u8BC1\u4E66"}, {".X.not.signed.by.specified.alias.es.", " X = \u672A\u7531\u6307\u5B9A\u522B\u540D\u7B7E\u540D"}, + {".q.unsigned.entry", + " ? = \u672A\u7B7E\u540D\u6761\u76EE"}, {"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"}, {".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"}, {".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"}, + {".Directory.entries.", "\uFF08\u76EE\u5F55\u6761\u76EE\uFF09"}, {"jar.is.unsigned", "jar \u672A\u7B7E\u540D\u3002"}, {"jar.treated.unsigned", diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java b/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java index c1ce47a19453e6848033ddd87968590226b87b4c..e9245430f666b2ee6d1cf2dc2e072546a68a0305 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java @@ -244,7 +244,7 @@ final class FingerPrint { private final Set methods = new HashSet<>(); public ClassAttributes() { - super(Opcodes.ASM7); + super(Opcodes.ASM9); } private boolean isPublic(int access) { diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties index 10f634baa085452f797e1e7c6736be8a0db3b60a..95744421c89829f25f2affab05721082bc44e82c 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -25,11 +25,11 @@ error.multiple.main.operations=Es ist nicht m\u00F6glich, mehrere "-cuxtid"-Optionen anzugeben error.cant.open=\u00D6ffnen nicht m\u00F6glich: {0} -error.illegal.option=Ung\u00FCltige Option: {0} +error.illegal.option=Unzul\u00E4ssige Option: {0} error.unrecognized.option=Unbekannte Option: {0} error.missing.arg=F\u00FCr die Option {0} ist ein Argument erforderlich error.bad.file.arg=Fehler beim Parsen der Dateiargumente -error.bad.option=Eine der Optionen -{ctxuid} muss angegeben werden. +error.bad.option=Eine der Optionen -{ctxuid} oder --validate muss angegeben werden. error.bad.cflag=Kennzeichen "c" erfordert Angabe von Manifest oder Eingabedateien. error.bad.uflag=Kennzeichen "u" erfordert Angabe von Manifest, Kennzeichen "e" oder Eingabedateien. error.bad.eflag=Kennzeichen "e" und Manifest mit dem Attribut "Main-Class" k\u00F6nnen nicht zusammen angegeben\nwerden. @@ -43,7 +43,7 @@ error.create.tempfile=Es konnte keine tempor\u00E4re Datei erstellt werden error.hash.dep=Abh\u00E4ngigkeiten bei Hashing-Modul {0}. Modul {1} kann nicht im Modulpfad gefunden werden error.module.options.without.info=--module-version oder --hash-modules ohne module-info.class error.no.operative.descriptor=Kein operativer Deskriptor f\u00FCr Release: {0} -error.no.root.descriptor=Kein Root-Moduldeskriptor. Geben Sie "--release" an +error.no.root.descriptor=Kein Root-Moduldeskriptor. Geben Sie --release an error.unable.derive.automodule=Moduldeskriptor kann nicht abgeleitet werden f\u00FCr: {0} error.unexpected.module-info=Unerwarteter Moduldeskriptor {0} error.module.descriptor.not.found=Moduldeskriptor nicht gefunden @@ -52,6 +52,8 @@ error.missing.provider=Serviceprovider nicht gefunden: {0} error.release.value.notnumber=Release {0} nicht g\u00FCltig error.release.value.toosmall=Release {0} nicht g\u00FCltig, muss >= 9 sein error.release.unexpected.versioned.entry=Unerwarteter versionierte Eintrag {0} f\u00FCr Release {1} +error.date.notvalid=Datum {0} ist keine g\u00FCltige erweiterte Datums-/Uhrzeitangabe mit Zeitunterschied und optionaler Zeitzone nach ISO-8601 +error.date.out.of.range=Datum {0} liegt nicht im g\u00FCltigen Bereich 1980-01-01T00:00:02Z bis 2099-12-31T23:59:59Z error.validator.jarfile.exception={0} kann nicht validiert werden: {1} error.validator.jarfile.invalid=ung\u00FCltige Multi-Release-JAR-Datei {0} gel\u00F6scht error.validator.bad.entry.name=Eintragsname hat das falsche Format, {0} @@ -75,6 +77,7 @@ warn.validator.identical.entry=Warnung: Eintrag {0} enth\u00E4lt eine Klasse, di warn.validator.resources.with.same.name=Warnung: Eintrag {0}, mehrere Ressourcen mit demselben Namen warn.validator.concealed.public.class=Warnung: Eintrag {0} ist eine \u00F6ffentliche Klasse\nin einem verdeckten Package. Wenn Sie diese JAR-Datei in den Classpath einf\u00FCgen, kommt es\nzu nicht kompatiblen \u00F6ffentlichen Schnittstellen warn.release.unexpected.versioned.entry=Unerwarteter versionierter Eintrag {0} +warn.flag.is.deprecated=Warnung: Die Option {0} ist veraltet, und ihre Entfernung in einem k\u00FCnftigen JDK-Release ist geplant\n out.added.manifest=Manifest wurde hinzugef\u00FCgt out.added.module-info=module-info hinzugef\u00FCgt: {0} out.automodule=Kein Moduldeskriptor gefunden. Automatisches Modul wurde abgeleitet. @@ -89,7 +92,7 @@ out.extracted=extrahiert: {0} out.inflated=\ vergr\u00F6\u00DFert: {0} out.size=(ein = {0}) (aus = {1}) -usage.compat=Kompatibilit\u00E4tsschnittstelle:\nVerwendung: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] Dateien] ...\nOptionen:\n -c Neues Archiv erstellen\n -t Inhaltsverzeichnis f\u00FCr Archiv anzeigen\n -x Benannte (oder alle) Dateien aus Archiv extrahieren\n -u Vorhandenes Archiv aktualisieren\n -v Ausgabe im Verbose-Modus aus Standardausgabe generieren\n -f Dateinamen f\u00FCr Archiv angeben\n -m Manifestinformationen aus angegebener Manifestdatei aufnehmen\n -n Pack200-Normalisierung nach Erstellung eines neuen Archivs ausf\u00FChren\n -e Anwendungseinstiegspunkt f\u00FCr in ausf\u00FChrbare JAR-Datei \n geb\u00FCndelte Standalone-Anwendung angeben\n -0 Nur speichern; keine ZIP-Komprimierung verwenden\n -P Komponenten mit vorangestelltem "/" (absoluter Pfad) und ".." (\u00FCbergeordnetes Verzeichnis) aus Dateinamen beibehalten\n -M Keine Manifestdatei f\u00FCr die Eintr\u00E4ge erstellen\n -i Indexinformationen f\u00FCr die angegebenen JAR-Dateien erstellen\n -C Zum angegebenen Verzeichnis wechseln und folgende Datei ber\u00FCcksichtigen\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nDer Name der Manifestdatei, der Name der Archivdatei und der Name des Einstiegspunktes werden\nin derselben Reihenfolge wie die Kennzeichen "m", "f" und "e" angegeben.\n\nBeispiel 1: Zwei Klassendateien in ein Archiv "classes.jar" archivieren: \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Mit der vorhandenen Manifestdatei "mymanifest" alle\n Dateien im Verzeichnis foo/ in "classes.jar" archivieren: \n jar cvfm classes.jar mymanifest -C foo/ .\n +usage.compat=Kompatibilit\u00E4tsschnittstelle\nVerwendung: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\nOptionen:\n -c erstellt ein neues Archiv\n -t listet das Inhaltsverzeichnis f\u00FCr das Archiv auf\n -x extrahiert die benannten (oder alle) Dateien aus dem Archiv\n -u aktualisiert ein vorhandenes Archiv\n -v generiert Verbose-Ausgabe zur Standardausgabe\n -f gibt den Archivdateinamen an\n -m schlie\u00DFt Manifestinformationen aus der angegebenen Manifestdatei ein\n -e gibt den Anwendungseinstiegspunkt f\u00FCr Standalone-Anwendungen an,\n die in einer ausf\u00FChrbaren JAR-Datei geb\u00FCndelt sind\n -0 speichert nur, keine ZIP-Komprimierung\n -P beh\u00E4lt die vorangestellten Komponenten "/" (absoluter Pfad) und ".." (\u00FCbergeordnetes Verzeichnis) aus dem Dateinamen bei\n -M generiert keine Manifestdatei f\u00FCr die Eintr\u00E4ge\n -i generiert Indexinformationen f\u00FCr die angegebenen JAR-Dateien\n -C wechselt zum angegebenen Verzeichnis und schlie\u00DFt die folgende Datei ein\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nDie Namen der Manifestdatei, der Archivdatei und des Einstiegspunkts werden\nin der gleichen Reihenfolge wie die Flags "m", "f" und "e" verarbeitet.\n\nBeispiel 1: Zwei Klassendateien in einem Archiv classes.jar archivieren: \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Eine vorhandene Manifestdatei "mymanifest" verwenden und alle\n Dateien im Verzeichnis foo/ directory in "classes.jar" archivieren: \n jar cvfm classes.jar mymanifest -C foo/ .\n main.usage.summary=Verwendung: jar [OPTION...] [ [--release VERSION] [-C dir] Dateien] ... main.usage.summary.try=Verwenden Sie "jar --help", um weitere Informationen anzuzeigen. @@ -102,11 +105,12 @@ main.help.opt.main.list=\ -t, --list Das Inhaltsverzeichnis f\u main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren main.help.opt.main.extract=\ -x, --extract Benannte (oder alle) Dateien aus dem Archiv extrahieren main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus +main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option\n validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API \u00FCber die verschiedenen Releaseversionen\n hinweg konsistent ist. main.help.opt.any=\ In jedem Modus g\u00FCltige Vorgangsmodifikatoren:\n\n -C DIR Zum angegebenen Verzeichnis wechseln und die folgende\n Datei aufnehmen main.help.opt.any.file=\ -f, --file=FILE Der Name der Archivdatei. Wenn Sie dies lauslassen, wird entweder stdin oder\n stdout verwendet, je nach Vorgang\n --release VERSION Speichert alle der folgenden Dateien in einem versionierten Verzeichnis\n der JAR-Datei (d.h. META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose Verbose-Ausgabe bei Standardausgabe generieren main.help.opt.create=\ Vorgangsmodifikatoren, die nur im Erstellungsmodus g\u00FCltig sind:\n -main.help.opt.create.normalize=\ -n, --normalize Normalisiert Informationen im neuen JAR-Archiv\n nach der Erstellung +main.help.opt.create.normalize=\ -n, --normalize Normalisiert Informationen im neuen JAR-Archiv\n nach der Erstellung. Diese Option ist veraltet, und ihre\n Entfernung in einem k\u00FCnftigen JDK-Release ist geplant main.help.opt.create.update=\ Vorgangsmodifikatoren, die nur im Erstellungs- und Aktualisierungsmodus g\u00FCltig sind:\n main.help.opt.create.update.main-class=\ -e, --main-class=CLASSNAME Der Anwendungseinstiegspunkt f\u00FCr Standalone-\n Anwendungen, die in einem modularen oder ausf\u00FChrbaren\n JAR-Archiv geb\u00FCndelt sind main.help.opt.create.update.manifest=\ -m, --manifest=FILE Die Manifestinformationen aus der angegebenen\n Manifestdatei aufnehmen @@ -118,8 +122,9 @@ main.help.opt.create.update.do-not-resolve-by-default=\ --do-not-resolve-by main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved Hinweis f\u00FCr ein Tool, eine Warnung auszugeben,\n wenn das Modul aufgel\u00F6st wird, entweder "deprecated", "deprecated-for-removal"\n oder "incubating" main.help.opt.create.update.index=\ Vorgangsmodifikatoren, die nur im Erstellungs-, Aktualisierungs- und Indexgenerierungsmodus g\u00FCltig sind:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress Nur speichern, keine ZIP-Komprimierung verwenden +main.help.opt.create.update.index.date=\ --date=TIMESTAMP Zeitstempel im erweiterten Datums-/Uhrzeitformat mit Zeitunterschied\n und optionaler Zeitzone nach ISO-8601, zur Verwendung f\u00FCr die Zeitstempel von\n Eintr\u00E4gen, z.B. "2022-02-12T12:30:00-05:00" main.help.opt.other=\ Weitere Optionen:\n -main.help.opt.other.help=\ -h, --help[:compat] Gibt diese Meldung oder optional die Kompatibilit\u00E4t, Hilfe an +main.help.opt.other.help=\ -?, -h, --help[:compat] Gibt diese Meldung oder optional die Kompatibilit\u00E4t, Hilfe an main.help.opt.other.help-extra=\ --help-extra Hilfe zu zus\u00E4tzlichen Optionen main.help.opt.other.version=\ --version Programmversion ausgeben main.help.postopt=\ Ein Archiv ist ein modulares JAR-Archiv, wenn der Moduldeskriptor "module-info.class"\n in der Root der angegebenen Verzeichnisse oder in der Root des JAR-Archivs selbst\n vorhanden ist. Die folgenden Vorg\u00E4nge sind nur g\u00FCltig, wenn Sie ein modulares JAR-Archiv\n erstellen oder ein vorhandenes nicht modulares JAR-Archiv aktualisieren: "--module-version",\n "--hash-modules" und "--modulepath".\n\n Obligatorische oder optionale Argumente zu langen Optionen sind auch f\u00FCr die jeweils\n zugeh\u00F6rigen kurzen Optionen obligatorisch oder optional. diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties index b17d8c1e08dea4733e3426eb43d9a82806b14327..a4cdec838f8be0b7551f3c4fdb9565cf090854aa 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -29,7 +29,7 @@ error.illegal.option=\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0} error.unrecognized.option=\u8A8D\u8B58\u3055\u308C\u306A\u3044\u30AA\u30D7\u30B7\u30E7\u30F3: {0} error.missing.arg=\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306B\u306F\u5F15\u6570\u304C\u5FC5\u8981\u3067\u3059\u3002 error.bad.file.arg=\u30D5\u30A1\u30A4\u30EB\u5F15\u6570\u306E\u89E3\u6790\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -error.bad.option=\u30AA\u30D7\u30B7\u30E7\u30F3-{ctxuid}\u306E\u3046\u3061\u306E1\u3064\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 +error.bad.option=\u30AA\u30D7\u30B7\u30E7\u30F3-{ctxuid}\u307E\u305F\u306F--validate\u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 error.bad.cflag=\u30D5\u30E9\u30B0'c'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002 error.bad.uflag=\u30D5\u30E9\u30B0'u'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304B'e'\u30D5\u30E9\u30B0\u3001\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002 error.bad.eflag='e'\u30D5\u30E9\u30B0\u3068'Main-Class'\u5C5E\u6027\u3092\u6301\u3064\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u540C\u6642\u306B\n\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002 @@ -52,6 +52,8 @@ error.missing.provider=\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u3 error.release.value.notnumber=\u30EA\u30EA\u30FC\u30B9{0}\u306F\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 error.release.value.toosmall=\u30EA\u30EA\u30FC\u30B9{0}\u306F\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u30029\u4EE5\u4E0A\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 error.release.unexpected.versioned.entry=\u30EA\u30EA\u30FC\u30B9{1}\u3067\u4E88\u671F\u3057\u306A\u3044\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u6E08\u30A8\u30F3\u30C8\u30EA{0} +error.date.notvalid=\u65E5\u4ED8{0}\u304C\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u3092\u6307\u5B9A\u3057\u305F\u3001\u6709\u52B9\u306AISO-8601\u306E\u62E1\u5F35\u30AA\u30D5\u30BB\u30C3\u30C8\u306E\u65E5\u6642\u3067\u306F\u3042\u308A\u307E\u305B\u3093 +error.date.out.of.range=\u65E5\u4ED8{0}\u304C\u6709\u52B9\u306A\u7BC4\u56F21980-01-01T00:00:02Z to 2099-12-31T23:59:59Z\u306B\u3042\u308A\u307E\u305B\u3093 error.validator.jarfile.exception={0}\u3092\u691C\u8A3C\u3067\u304D\u307E\u305B\u3093: {1} error.validator.jarfile.invalid=\u7121\u52B9\u306A\u30DE\u30EB\u30C1\u30EA\u30EA\u30FC\u30B9jar\u30D5\u30A1\u30A4\u30EB{0}\u304C\u524A\u9664\u3055\u308C\u307E\u3057\u305F error.validator.bad.entry.name=\u30A8\u30F3\u30C8\u30EA\u540D\u304C\u4E0D\u6B63\u3067\u3059: {0} @@ -103,6 +105,7 @@ main.help.opt.main.list=\ -t\u3001--list \u30A2\u30FC\u30AB\u30 main.help.opt.main.update=\ -u\u3001--update \u65E2\u5B58\u306Ejar\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u66F4\u65B0\u3057\u307E\u3059 main.help.opt.main.extract=\ -x\u3001--extract \u6307\u5B9A\u306E(\u307E\u305F\u306F\u3059\u3079\u3066\u306E)\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u62BD\u51FA\u3057\u307E\u3059 main.help.opt.main.describe-module=\ -d, --describe-module \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u307E\u305F\u306F\u81EA\u52D5\u30E2\u30B8\u30E5\u30FC\u30EB\u540D\u3092\u51FA\u529B\u3057\u307E\u3059 +main.help.opt.main.validate=\ --validate jar\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u691C\u8A3C\u3057\u307E\u3059\u3002\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\n \u8907\u6570\u30EA\u30EA\u30FC\u30B9\u306Ejar\u30A2\u30FC\u30AB\u30A4\u30D6\u3067\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3055\u308C\u305FAPI\u304C\n \u3059\u3079\u3066\u306E\u7570\u306A\u308B\u30EA\u30EA\u30FC\u30B9\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u4E00\u8CAB\u3057\u3066\u3044\u308B\u3053\u3068\u3092\n \u691C\u8A3C\u3057\u307E\u3059\u3002 main.help.opt.any=\ \u3069\u306E\u30E2\u30FC\u30C9\u3067\u3082\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n\n -C DIR \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u6B21\u306E\u30D5\u30A1\u30A4\u30EB\u3092\n \u53D6\u308A\u8FBC\u307F\u307E\u3059 main.help.opt.any.file=\ -f\u3001--file=FILE \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u7701\u7565\u3057\u305F\u5834\u5408\u3001stdin\u307E\u305F\u306F\n stdout\u306E\u3044\u305A\u308C\u304B\u304C\u64CD\u4F5C\u306B\u57FA\u3065\u3044\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\n --release VERSION \u6B21\u306E\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3092jar\u306E\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n (\u3064\u307E\u308A\u3001META-INF/versions/VERSION/)\u306B\u914D\u7F6E\u3057\u307E\u3059 main.help.opt.any.verbose=\ -v\u3001--verbose \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3057\u307E\u3059 @@ -119,6 +122,7 @@ main.help.opt.create.update.do-not-resolve-by-default=\ --do-not-resolve-by main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved \u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u89E3\u6C7A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u306F\u3001\u8B66\u544A\u3092\u767A\u884C\u3059\u308B\n \u30C4\u30FC\u30EB\u306E\u30D2\u30F3\u30C8\u3002\u975E\u63A8\u5968\u3001\u524A\u9664\u4E88\u5B9A\u306E\u975E\u63A8\u5968\u307E\u305F\u306F\n \u5B9F\u9A13\u7684\u306E\u3044\u305A\u308C\u304B main.help.opt.create.update.index=\ \u4F5C\u6210\u3001\u66F4\u65B0\u304A\u3088\u3073\u7D22\u5F15\u751F\u6210\u30E2\u30FC\u30C9\u3067\u306E\u307F\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u307E\u305B\u3093 +main.help.opt.create.update.index.date=\ --date=TIMESTAMP \u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u5F62\u5F0F\u3092\u6307\u5B9A\u3057\u305FISO-8601\u62E1\u5F35\u30AA\u30D5\u30BB\u30C3\u30C8\n \u306E\u65E5\u6642\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3002\u30A8\u30F3\u30C8\u30EA\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u4F7F\u7528\u4F8B\u306F\u3001\n "2022-02-12T12:30:00-05:00"\u3067\u3059 main.help.opt.other=\ \u305D\u306E\u4ED6\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n main.help.opt.other.help=\ -?\u3001-h\u3001--help[:compat] \u3053\u308C(\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u4E92\u63DB\u6027)\u3092help\u306B\u6307\u5B9A\u3057\u307E\u3059 main.help.opt.other.help-extra=\ --help-extra \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u63D0\u4F9B\u3057\u307E\u3059 diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties index 36889f522cb1ba079045b03131c7aae0a6497587..5a4832d0bd46b307f8dc4e452b15ea64e2292827 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -29,7 +29,7 @@ error.illegal.option=\u975E\u6CD5\u9009\u9879: {0} error.unrecognized.option=\u65E0\u6CD5\u8BC6\u522B\u7684\u9009\u9879: {0} error.missing.arg=\u9009\u9879{0}\u9700\u8981\u53C2\u6570 error.bad.file.arg=\u89E3\u6790\u6587\u4EF6\u53C2\u6570\u65F6\u51FA\u9519 -error.bad.option=\u5FC5\u987B\u6307\u5B9A {ctxuid} \u4E2D\u7684\u4EFB\u4E00\u9009\u9879\u3002 +error.bad.option=\u5FC5\u987B\u6307\u5B9A -{ctxuid} \u6216 --validate \u9009\u9879\u4E4B\u4E00\u3002 error.bad.cflag='c' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355\u6216\u8F93\u5165\u6587\u4EF6! error.bad.uflag='u' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355, 'e' \u6807\u8BB0\u6216\u8F93\u5165\u6587\u4EF6! error.bad.eflag=\u4E0D\u80FD\u540C\u65F6\u6307\u5B9A 'e' \u6807\u8BB0\u548C\u5177\u6709 'Main-Class' \u5C5E\u6027\u7684\n\u6E05\u5355! @@ -52,6 +52,8 @@ error.missing.provider=\u672A\u627E\u5230\u670D\u52A1\u63D0\u4F9B\u65B9: {0} error.release.value.notnumber=\u53D1\u884C\u7248 {0} \u65E0\u6548 error.release.value.toosmall=\u53D1\u884C\u7248 {0} \u65E0\u6548, \u5FC5\u987B >= 9 error.release.unexpected.versioned.entry=\u53D1\u884C\u7248 {1} \u5B58\u5728\u610F\u5916\u7684\u7248\u672C\u5316\u6761\u76EE {0} +error.date.notvalid=\u65E5\u671F {0} \u4E0D\u662F\u5177\u6709\u53EF\u9009\u65F6\u533A\u7684\u6709\u6548 ISO-8601 \u6269\u5C55\u504F\u79FB\u65E5\u671F\u65F6\u95F4 +error.date.out.of.range=\u65E5\u671F {0} \u4E0D\u5728 1980-01-01T00:00:02Z \u5230 2099-12-31T23:59:59Z \u8FD9\u4E00\u6709\u6548\u8303\u56F4\u5185 error.validator.jarfile.exception=\u65E0\u6CD5\u9A8C\u8BC1 {0}: {1} error.validator.jarfile.invalid=\u5220\u9664\u7684\u591A\u53D1\u884C\u7248 jar \u6587\u4EF6 {0} \u65E0\u6548 error.validator.bad.entry.name=\u6761\u76EE\u540D\u79F0\u683C\u5F0F\u9519\u8BEF, {0} @@ -103,6 +105,7 @@ main.help.opt.main.list=\ -t, --list \u5217\u51FA\u6863\u6848\u main.help.opt.main.update=\ -u, --update \u66F4\u65B0\u73B0\u6709 jar \u6863\u6848 main.help.opt.main.extract=\ -x, --extract \u4ECE\u6863\u6848\u4E2D\u63D0\u53D6\u6307\u5B9A\u7684 (\u6216\u5168\u90E8) \u6587\u4EF6 main.help.opt.main.describe-module=\ -d, --describe-module \u8F93\u51FA\u6A21\u5757\u63CF\u8FF0\u7B26\u6216\u81EA\u52A8\u6A21\u5757\u540D\u79F0 +main.help.opt.main.validate=\ --validate \u9A8C\u8BC1 jar \u6863\u6848\u7684\u5185\u5BB9\u3002\u6B64\u9009\u9879\n \u5C06\u9A8C\u8BC1\u7531\u591A\u53D1\u884C\u7248 jar \u6863\u6848\u5BFC\u51FA\n \u7684 API \u5728\u6240\u6709\u4E0D\u540C\u7684\u53D1\u884C\u7248\u672C\u4E2D\n \u662F\u5426\u4E00\u81F4\u3002 main.help.opt.any=\ \u5728\u4EFB\u610F\u6A21\u5F0F\u4E0B\u6709\u6548\u7684\u64CD\u4F5C\u4FEE\u9970\u7B26:\n\n -C DIR \u66F4\u6539\u4E3A\u6307\u5B9A\u7684\u76EE\u5F55\u5E76\u5305\u542B\n \u4EE5\u4E0B\u6587\u4EF6 main.help.opt.any.file=\ -f, --file=FILE \u6863\u6848\u6587\u4EF6\u540D\u3002\u7701\u7565\u65F6, \u57FA\u4E8E\u64CD\u4F5C\n \u4F7F\u7528 stdin \u6216 stdout\n --release VERSION \u5C06\u4E0B\u9762\u7684\u6240\u6709\u6587\u4EF6\u90FD\u653E\u5728\n jar \u7684\u7248\u672C\u5316\u76EE\u5F55\u4E2D (\u5373 META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose \u5728\u6807\u51C6\u8F93\u51FA\u4E2D\u751F\u6210\u8BE6\u7EC6\u8F93\u51FA @@ -119,6 +122,7 @@ main.help.opt.create.update.do-not-resolve-by-default=\ --do-not-resolve-by main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved \u63D0\u793A\u5DE5\u5177\u5728\u89E3\u6790\u6A21\u5757\u540E\u53D1\u51FA\u8B66\u544A\u3002\n \u53EF\u4EE5\u4E3A deprecated, deprecated-for-removal\n \u6216 incubating \u4E4B\u4E00 main.help.opt.create.update.index=\ \u53EA\u5728\u521B\u5EFA, \u66F4\u65B0\u548C\u751F\u6210\u7D22\u5F15\u6A21\u5F0F\u4E0B\u6709\u6548\u7684\u64CD\u4F5C\u4FEE\u9970\u7B26:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress \u4EC5\u5B58\u50A8; \u4E0D\u4F7F\u7528 ZIP \u538B\u7F29 +main.help.opt.create.update.index.date=\ --date=TIMESTAMP \u5177\u6709\u53EF\u9009\u65F6\u533A\u7684 ISO-8601 \u6269\u5C55\u504F\u79FB\n \u65E5\u671F\u65F6\u95F4\u683C\u5F0F\u7684\u65F6\u95F4\u6233\uFF08\u7528\u4E8E\u6761\u76EE\u7684\u65F6\u95F4\u6233\uFF09\uFF0C\n \u4F8B\u5982\uFF0C"2022-02-12T12:30:00-05:00" main.help.opt.other=\ \u5176\u4ED6\u9009\u9879:\n main.help.opt.other.help=\ -?, -h, --help[:compat] \u63D0\u4F9B\u6B64\u5E2E\u52A9\uFF0C\u4E5F\u53EF\u4EE5\u9009\u62E9\u6027\u5730\u63D0\u4F9B\u517C\u5BB9\u6027\u5E2E\u52A9 main.help.opt.other.help-extra=\ --help-extra \u63D0\u4F9B\u989D\u5916\u9009\u9879\u7684\u5E2E\u52A9 diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 index bcf457fb6f65603e70b40af8bc5150667766e584..9cf2df33b22b23aba16f78b0b242376e2c17b846 100644 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ b/src/jdk.jartool/share/man/jarsigner.1 @@ -766,7 +766,7 @@ The file can be a sequence of concatenated X.509 certificates, or a single PKCS#7 formatted data block, either in binary encoding format or in printable encoding format (also known as Base64 encoding) as defined by \f[B]Internet RFC 1421 Certificate Encoding Standard\f[R] -[http://tools.ietf.org/html/rfc1421]. +[https://tools.ietf.org/html/rfc1421]. .RS .RE .TP diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java index 944709742471ca183d7f45e748f33082edc06ff6..cb41ebb6189870d9b31668d113cdb7cedc6253c3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.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 @@ -26,9 +26,9 @@ package jdk.javadoc.internal.api; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import javax.tools.DocumentationTool.DocumentationTask; @@ -67,9 +67,9 @@ public class JavadocTaskImpl implements DocumentationTask { this.context = context; this.docletClass = docletClass; - this.options = (options == null) ? Collections.emptySet() + this.options = (options == null) ? Set.of() : nullCheck(options); - this.fileObjects = (fileObjects == null) ? Collections.emptySet() + this.fileObjects = (fileObjects == null) ? Set.of() : nullCheck(fileObjects); setLocale(Locale.getDefault()); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java index 39c15a8231338ed947b7bafb5ebb5583e7c52bad..7cbf9544105f4919eba480e86858af599a2badaf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.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 @@ -100,52 +100,37 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite member, content, null, false); } - /** - * Add the summary link for the member. - * - * @param context the id of the context where the link will be printed - * @param te the type element being linked to - * @param member the member being linked to - * @param tdSummary the content tree to which the link will be added - */ @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement te, Element member, - Content tdSummary) { + Content target) { ExecutableElement ee = (ExecutableElement)member; Content memberLink = writer.getDocLink(context, te, ee, name(ee), HtmlStyle.memberNameLink); - Content code = HtmlTree.CODE(memberLink); + var code = HtmlTree.CODE(memberLink); addParameters(ee, code); - tdSummary.add(code); + target.add(code); } - /** - * Add the inherited summary link for the member. - * - * @param te the type element that we should link to - * @param member the member being linked to - * @param linksTree the content tree to which the link will be added - */ @Override - protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) { - linksTree.add(writer.getDocLink(MEMBER, te, member, name(member))); + protected void addInheritedSummaryLink(TypeElement te, Element member, Content target) { + target.add(writer.getDocLink(MEMBER, te, member, name(member))); } /** * Add the parameter for the executable member. * - * @param param the parameter that needs to be written. + * @param param the parameter that needs to be added. * @param paramType the type of the parameter. * @param isVarArg true if this is a link to var arg. - * @param tree the content tree to which the parameter information will be added. + * @param target the content to which the parameter information will be added. */ protected void addParam(VariableElement param, TypeMirror paramType, boolean isVarArg, - Content tree) { + Content target) { Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM, paramType).varargs(isVarArg)); - tree.add(link); + target.add(link); if(name(param).length() > 0) { - tree.add(Entity.NO_BREAK_SPACE); - tree.add(name(param)); + target.add(Entity.NO_BREAK_SPACE); + target.add(name(param)); } } @@ -156,18 +141,18 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite * * @param member the member to write receiver annotations for. * @param rcvrType the receiver type. - * @param tree the content tree to which the information will be added. + * @param target the content to which the information will be added. */ - protected void addReceiver(ExecutableElement member, TypeMirror rcvrType, Content tree) { + protected void addReceiver(ExecutableElement member, TypeMirror rcvrType, Content target) { var info = new HtmlLinkInfo(configuration, RECEIVER_TYPE, rcvrType); info.linkToSelf = false; - tree.add(writer.getLink(info)); - tree.add(Entity.NO_BREAK_SPACE); + target.add(writer.getLink(info)); + target.add(Entity.NO_BREAK_SPACE); if (member.getKind() == ElementKind.CONSTRUCTOR) { - tree.add(utils.getTypeName(rcvrType, false)); - tree.add("."); + target.add(utils.getTypeName(rcvrType, false)); + target.add("."); } - tree.add("this"); + target.add("this"); } /** @@ -205,15 +190,15 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite * Add all the parameters for the executable member. * * @param member the member to write parameters for. - * @param htmltree the content tree to which the parameters information will be added. + * @param target the content to which the parameters information will be added. */ - protected void addParameters(ExecutableElement member, Content htmltree) { - Content paramTree = getParameters(member, false); - if (paramTree.charCount() > 2) { + protected void addParameters(ExecutableElement member, Content target) { + Content params = getParameters(member, false); + if (params.charCount() > 2) { // only add for non-empty parameters - htmltree.add(new HtmlTree(TagName.WBR)); + target.add(new HtmlTree(TagName.WBR)); } - htmltree.add(paramTree); + target.add(params); } /** @@ -221,22 +206,22 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite * * @param member the member to write parameters for. * @param includeAnnotations true if annotation information needs to be added. - * @return the content tree containing the parameter information + * @return the parameter information */ protected Content getParameters(ExecutableElement member, boolean includeAnnotations) { - Content paramTree = new ContentBuilder(); - paramTree.add("("); + Content result = new ContentBuilder(); + result.add("("); String sep = ""; List parameters = member.getParameters(); TypeMirror rcvrType = member.getReceiverType(); if (includeAnnotations && rcvrType != null && isAnnotatedReceiver(rcvrType)) { - addReceiver(member, rcvrType, paramTree); + addReceiver(member, rcvrType, result); sep = "," + DocletConstants.NL + " "; } int paramstart; ExecutableType instMeth = utils.asInstantiatedMethodType(typeElement, member); for (paramstart = 0; paramstart < parameters.size(); paramstart++) { - paramTree.add(sep); + result.add(sep); VariableElement param = parameters.get(paramstart); TypeMirror paramType = instMeth.getParameterTypes().get(paramstart); @@ -244,56 +229,56 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite if (includeAnnotations) { Content annotationInfo = writer.getAnnotationInfo(param, false); if (!annotationInfo.isEmpty()) { - paramTree.add(annotationInfo) + result.add(annotationInfo) .add(DocletConstants.NL) .add(" "); } } addParam(param, paramType, - (paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree); + (paramstart == parameters.size() - 1) && member.isVarArgs(), result); break; } } for (int i = paramstart + 1; i < parameters.size(); i++) { - paramTree.add(","); - paramTree.add(DocletConstants.NL); - paramTree.add(" "); + result.add(","); + result.add(DocletConstants.NL); + result.add(" "); if (includeAnnotations) { Content annotationInfo = writer.getAnnotationInfo(parameters.get(i), false); if (!annotationInfo.isEmpty()) { - paramTree.add(annotationInfo) + result.add(annotationInfo) .add(DocletConstants.NL) .add(" "); } } addParam(parameters.get(i), instMeth.getParameterTypes().get(i), (i == parameters.size() - 1) && member.isVarArgs(), - paramTree); + result); } - paramTree.add(")"); - return paramTree; + result.add(")"); + return result; } /** - * Get a content tree containing the exception information for the executable member. + * Get the exception information for the executable member. * - * @param member the member to write exceptions for. - * @return the content tree containing the exceptions information. + * @param member the member to get the exception information for + * @return the exception information */ protected Content getExceptions(ExecutableElement member) { List exceptions = utils.asInstantiatedMethodType(typeElement, member).getThrownTypes(); - Content htmlTree = new ContentBuilder(); + Content result = new ContentBuilder(); for (TypeMirror t : exceptions) { - if (!htmlTree.isEmpty()) { - htmlTree.add(","); - htmlTree.add(DocletConstants.NL); + if (!result.isEmpty()) { + result.add(","); + result.add(DocletConstants.NL); } Content link = writer.getLink(new HtmlLinkInfo(configuration, THROWS_TYPE, t)); - htmlTree.add(link); + result.add(link); } - return htmlTree; + return result; } protected TypeElement implementsMethodInIntfac(ExecutableElement method, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index f717cdf2cf4bb276e957dfdcf7e5c420e728af4a..3ed4aff1a1af41ffb381736c7a5b901c27fe5dae 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.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 @@ -91,9 +91,9 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe /** * Adds the summary label for the member. * - * @param memberTree the content tree to which the label will be added + * @param content the content to which the label will be added */ - public abstract void addSummaryLabel(Content memberTree); + public abstract void addSummaryLabel(Content content); /** * Returns the summary table header for the member. @@ -126,28 +126,28 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe /** * Adds inherited summary label for the member. * - * @param typeElement the type element to which to link to - * @param inheritedTree the content tree to which the inherited summary label will be added + * @param typeElement the type element to which to link to + * @param content the content to which the inherited summary label will be added */ - public abstract void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree); + public abstract void addInheritedSummaryLabel(TypeElement typeElement, Content content); /** * Adds the summary type for the member. * - * @param member the member to be documented - * @param tdSummaryType the content tree to which the type will be added + * @param member the member to be documented + * @param content the content to which the type will be added */ - protected abstract void addSummaryType(Element member, Content tdSummaryType); + protected abstract void addSummaryType(Element member, Content content); /** * Adds the summary link for the member. * * @param typeElement the type element to be documented * @param member the member to be documented - * @param tdSummary the content tree to which the link will be added + * @param content the content to which the link will be added */ - protected void addSummaryLink(TypeElement typeElement, Element member, Content tdSummary) { - addSummaryLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member, tdSummary); + protected void addSummaryLink(TypeElement typeElement, Element member, Content content) { + addSummaryLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member, content); } /** @@ -156,41 +156,41 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe * @param context the id of the context where the link will be printed * @param typeElement the type element to be documented * @param member the member to be documented - * @param tdSummary the content tree to which the summary link will be added + * @param content the content to which the summary link will be added */ protected abstract void addSummaryLink(HtmlLinkInfo.Kind context, - TypeElement typeElement, Element member, Content tdSummary); + TypeElement typeElement, Element member, Content content); /** * Adds the inherited summary link for the member. * * @param typeElement the type element to be documented * @param member the member to be documented - * @param linksTree the content tree to which the inherited summary link will be added + * @param target the content to which the inherited summary link will be added */ protected abstract void addInheritedSummaryLink(TypeElement typeElement, - Element member, Content linksTree); + Element member, Content target); /** * Returns a link for summary (deprecated, preview) pages. * * @param member the member being linked to * - * @return a content tree representing the link + * @return the link */ protected abstract Content getSummaryLink(Element member); /** - * Adds the modifier and type for the member in the member summary. + * Adds the modifiers and type for the member in the member summary. * - * @param member the member to add the type for - * @param type the type to add - * @param tdSummaryType the content tree to which the modified and type will be added + * @param member the member to add the modifiers and type for + * @param type the type to add + * @param target the content to which the modifiers and type will be added */ - protected void addModifierAndType(Element member, TypeMirror type, - Content tdSummaryType) { - HtmlTree code = new HtmlTree(TagName.CODE); - addModifier(member, code); + protected void addModifiersAndType(Element member, TypeMirror type, + Content target) { + var code = new HtmlTree(TagName.CODE); + addModifiers(member, code); if (type == null) { code.add(switch (member.getKind()) { case ENUM -> "enum"; @@ -219,64 +219,63 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe writer.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.SUMMARY_RETURN_TYPE, type))); } - tdSummaryType.add(code); + target.add(code); } /** - * Adds the modifier for the member. + * Adds the modifiers for the member. * - * @param member the member to add the type for - * @param code the content tree to which the modifier will be added + * @param member the member to add the modifiers for + * @param target the content to which the modifiers will be added */ - private void addModifier(Element member, Content code) { + private void addModifiers(Element member, Content target) { if (utils.isProtected(member)) { - code.add("protected "); + target.add("protected "); } else if (utils.isPrivate(member)) { - code.add("private "); + target.add("private "); } else if (!utils.isPublic(member)) { // Package private - code.add(resources.getText("doclet.Package_private")); - code.add(" "); + target.add(resources.getText("doclet.Package_private")); + target.add(" "); } - boolean isAnnotatedTypeElement = utils.isAnnotationType(member.getEnclosingElement()); - if (!isAnnotatedTypeElement && utils.isMethod(member)) { - if (!utils.isInterface(member.getEnclosingElement()) && utils.isAbstract(member)) { - code.add("abstract "); + if (!utils.isAnnotationInterface(member.getEnclosingElement()) && utils.isMethod(member)) { + if (!utils.isPlainInterface(member.getEnclosingElement()) && utils.isAbstract(member)) { + target.add("abstract "); } if (utils.isDefault(member)) { - code.add("default "); + target.add("default "); } } if (utils.isStatic(member)) { - code.add("static "); + target.add("static "); } if (!utils.isEnum(member) && utils.isFinal(member)) { - code.add("final "); + target.add("final "); } } /** * Adds the deprecated information for the given member. * - * @param member the member being documented. - * @param contentTree the content tree to which the deprecated information will be added. + * @param member the member being documented. + * @param target the content to which the deprecated information will be added. */ - protected void addDeprecatedInfo(Element member, Content contentTree) { + protected void addDeprecatedInfo(Element member, Content target) { Content output = (new DeprecatedTaglet()).getAllBlockTagOutput(member, writer.getTagletWriterInstance(false)); if (!output.isEmpty()) { - contentTree.add(HtmlTree.DIV(HtmlStyle.deprecationBlock, output)); + target.add(HtmlTree.DIV(HtmlStyle.deprecationBlock, output)); } } /** * Adds the comment for the given member. * - * @param member the member being documented. - * @param htmlTree the content tree to which the comment will be added. + * @param member the member being documented. + * @param content the content to which the comment will be added. */ - protected void addComment(Element member, Content htmlTree) { + protected void addComment(Element member, Content content) { if (!utils.getFullBody(member).isEmpty()) { - writer.addInlineComment(member, htmlTree); + writer.addInlineComment(member, content); } } @@ -284,10 +283,10 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe * Add the preview information for the given member. * * @param member the member being documented. - * @param contentTree the content tree to which the preview information will be added. + * @param content the content to which the preview information will be added. */ - protected void addPreviewInfo(Element member, Content contentTree) { - writer.addPreviewInfo(member, contentTree); + protected void addPreviewInfo(Element member, Content content) { + writer.addPreviewInfo(member, content); } protected String name(Element member) { @@ -295,13 +294,13 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe } /** - * Adds use information to the documentation tree. + * Adds use information to the documentation. * - * @param members list of program elements for which the use information will be added - * @param heading the section heading - * @param contentTree the content tree to which the use information will be added + * @param members list of program elements for which the use information will be added + * @param heading the section heading + * @param content the content to which the use information will be added */ - protected void addUseInfo(List members, Content heading, Content contentTree) { + protected void addUseInfo(List members, Content heading, Content content) { if (members == null || members.isEmpty()) { return; } @@ -322,15 +321,13 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe Content typeContent = new ContentBuilder(); if (te != null && !utils.isConstructor(element) - && !utils.isClass(element) - && !utils.isInterface(element) - && !utils.isAnnotationType(element)) { - HtmlTree name = new HtmlTree(TagName.SPAN); + && !utils.isTypeElement(element)) { + var name = new HtmlTree(TagName.SPAN); name.setStyle(HtmlStyle.typeNameLabel); name.add(name(te) + "."); typeContent.add(name); } - addSummaryLink(utils.isClass(element) || utils.isInterface(element) + addSummaryLink(utils.isClass(element) || utils.isPlainInterface(element) ? HtmlLinkInfo.Kind.CLASS_USE : HtmlLinkInfo.Kind.MEMBER, te, element, typeContent); @@ -338,7 +335,7 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe writer.addSummaryLinkComment(element, desc); useTable.addRow(summaryType, typeContent, desc); } - contentTree.add(useTable); + content.add(useTable); } protected void serialWarning(Element e, String key, String a1, String a2) { @@ -371,24 +368,24 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe @Override public void addInheritedMemberSummary(TypeElement tElement, Element nestedClass, boolean isFirst, boolean isLast, - Content linksTree) { - writer.addInheritedMemberSummary(this, tElement, nestedClass, isFirst, linksTree); + Content content) { + writer.addInheritedMemberSummary(this, tElement, nestedClass, isFirst, content); } @Override public Content getInheritedSummaryHeader(TypeElement tElement) { - Content inheritedTree = writer.getMemberInheritedTree(); - writer.addInheritedSummaryHeader(this, tElement, inheritedTree); - return inheritedTree; + Content c = writer.getMemberInherited(); + writer.addInheritedSummaryHeader(this, tElement, c); + return c; } @Override - public Content getInheritedSummaryLinksTree() { + public Content getInheritedSummaryLinks() { return new HtmlTree(TagName.CODE); } @Override - public Content getSummaryTableTree(TypeElement tElement) { + public Content getSummaryTable(TypeElement tElement) { if (tElement != typeElement) { throw new IllegalStateException(); } @@ -400,8 +397,8 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe } @Override - public Content getMemberTree(Content memberTree) { - return writer.getMemberTree(memberTree); + public Content getMember(Content memberContent) { + return writer.getMember(memberContent); } @Override @@ -410,8 +407,8 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe } @Override - public Content getMemberListItem(Content memberTree) { - return writer.getMemberListItem(memberTree); + public Content getMemberListItem(Content memberContent) { + return writer.getMemberListItem(memberContent); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java index 40100d6fd278846308f6d52e5ec91ec9318c2a60..71d958521b078eea9e5e83e8dede3435daa808b8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.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 @@ -62,35 +62,34 @@ public abstract class AbstractOverviewIndexWriter extends HtmlDocletWriter { * summary at the top of the page and generate a link to the description, * which is added at the end of this page. * - * @param main the documentation tree to which the overview header will be added + * @param target the content to which the overview header will be added */ - protected void addOverviewHeader(Content main) { - addConfigurationTitle(main); - addOverviewComment(main); - addOverviewTags(main); + protected void addOverviewHeader(Content target) { + addConfigurationTitle(target); + addOverviewComment(target); + addOverviewTags(target); } /** * Adds the overview comment as provided in the file specified by the * "-overview" option on the command line. * - * @param htmltree the documentation tree to which the overview comment will - * be added + * @param content the content to which the overview comment will be added */ - protected void addOverviewComment(Content htmltree) { + protected void addOverviewComment(Content content) { if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { - addInlineComment(configuration.overviewElement, htmltree); + addInlineComment(configuration.overviewElement, content); } } /** * Adds the block tags provided in the file specified by the "-overview" option. * - * @param htmlTree the content tree to which the tags will be added + * @param content the content to which the tags will be added */ - protected void addOverviewTags(Content htmlTree) { + protected void addOverviewTags(Content content) { if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { - addTagsInfo(configuration.overviewElement, htmlTree); + addTagsInfo(configuration.overviewElement, content); } } @@ -118,25 +117,25 @@ public abstract class AbstractOverviewIndexWriter extends HtmlDocletWriter { } /** - * Adds the index to the documentation tree. + * Adds the index to the documentation. * - * @param main the document tree to which the packages/modules list will be added + * @param target the content to which the packages/modules list will be added */ - protected abstract void addIndex(Content main); + protected abstract void addIndex(Content target); /** - * Adds the doctitle to the documentation tree, if it is specified on the command line. + * Adds the doctitle to the documentation, if it is specified on the command line. * - * @param body the document tree to which the title will be added + * @param target the content to which the title will be added */ - protected void addConfigurationTitle(Content body) { + protected void addConfigurationTitle(Content target) { String doctitle = configuration.getOptions().docTitle(); if (!doctitle.isEmpty()) { - Content title = new RawHtml(doctitle); - Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, + var title = new RawHtml(doctitle); + var heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, title); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); - body.add(div); + var div = HtmlTree.DIV(HtmlStyle.header, heading); + target.add(div); } } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java index 96ee6251a4e1e63b02b2db01de69b1675ed21f94..5d40167bcbadfb6f771457368c9fa17bc5283fdb 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.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 @@ -77,14 +77,14 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { * @param parent the superclass or superinterface of the sset * @param collection a collection of the sub-classes at this level * @param isEnum true if we are generating a tree for enums - * @param contentTree the content tree to which the level information will be added + * @param content the content to which the level information will be added */ protected void addLevelInfo(TypeElement parent, Collection collection, - boolean isEnum, Content contentTree) { + boolean isEnum, Content content) { if (!collection.isEmpty()) { - Content ul = new HtmlTree(TagName.UL); + var ul = new HtmlTree(TagName.UL); for (TypeElement local : collection) { - HtmlTree li = new HtmlTree(TagName.LI); + var li = new HtmlTree(TagName.LI); li.setStyle(HtmlStyle.circle); addPartialInfo(local, li); addExtendsImplements(parent, local, li); @@ -92,7 +92,7 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { isEnum, li); // Recurse ul.add(li); } - contentTree.add(ul); + content.add(ul); } } @@ -103,7 +103,7 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { * @param sset classes which are at the most base level, all the * other classes in this run will derive from these classes * @param heading heading for the tree - * @param content the content tree to which the tree will be added + * @param content the content to which the tree will be added */ protected void addTree(SortedSet sset, String heading, Content content) { addTree(sset, heading, content, false); @@ -114,12 +114,12 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { if (!sset.isEmpty()) { TypeElement firstTypeElement = sset.first(); Content headingContent = contents.getContent(heading); - Content sectionHeading = HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, + var sectionHeading = HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, headingContent); - HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.hierarchy, sectionHeading); - addLevelInfo(!utils.isInterface(firstTypeElement) ? firstTypeElement : null, - sset, isEnums, htmlTree); - content.add(htmlTree); + var section = HtmlTree.SECTION(HtmlStyle.hierarchy, sectionHeading); + addLevelInfo(!utils.isPlainInterface(firstTypeElement) ? firstTypeElement : null, + sset, isEnums, section); + content.add(section); } } @@ -129,37 +129,37 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { * * @param parent the parent class of the class being documented * @param typeElement the TypeElement under consideration - * @param contentTree the content tree to which the information will be added + * @param content the content to which the information will be added */ protected void addExtendsImplements(TypeElement parent, TypeElement typeElement, - Content contentTree) + Content content) { SortedSet interfaces = new TreeSet<>(comparators.makeGeneralPurposeComparator()); typeElement.getInterfaces().forEach(t -> interfaces.add(utils.asTypeElement(t))); - if (interfaces.size() > (utils.isInterface(typeElement) ? 1 : 0)) { + if (interfaces.size() > (utils.isPlainInterface(typeElement) ? 1 : 0)) { boolean isFirst = true; for (TypeElement intf : interfaces) { if (parent != intf) { if (utils.isPublic(intf) || utils.isLinkable(intf)) { if (isFirst) { isFirst = false; - if (utils.isInterface(typeElement)) { - contentTree.add(" ("); - contentTree.add(contents.also); - contentTree.add(" extends "); + if (utils.isPlainInterface(typeElement)) { + content.add(" ("); + content.add(contents.also); + content.add(" extends "); } else { - contentTree.add(" (implements "); + content.add(" (implements "); } } else { - contentTree.add(", "); + content.add(", "); } - addPreQualifiedClassLink(HtmlLinkInfo.Kind.TREE, intf, contentTree); + addPreQualifiedClassLink(HtmlLinkInfo.Kind.TREE, intf, content); } } } if (!isFirst) { - contentTree.add(")"); + content.add(")"); } } } @@ -168,9 +168,9 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { * Add information about the class kind, if it's a "class" or "interface". * * @param typeElement the class being documented - * @param contentTree the content tree to which the information will be added + * @param content the content to which the information will be added */ - protected void addPartialInfo(TypeElement typeElement, Content contentTree) { - addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind.TREE, typeElement, contentTree); + protected void addPartialInfo(TypeElement typeElement, Content content) { + addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind.TREE, typeElement, content); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java index a2d4f51e45eb7d63379178ca24db77553fde7bfe..79c01e1a8716eeae33b332438a5586bab2083e88 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.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 @@ -97,31 +97,31 @@ public class AllClassesIndexWriter extends HtmlDocletWriter { addContents(allClassesContent); Content mainContent = new ContentBuilder(); mainContent.add(allClassesContent); - HtmlTree bodyTree = getBody(getWindowTitle(label)); - bodyTree.add(new BodyContents() + HtmlTree body = getBody(getWindowTitle(label)); + body.add(new BodyContents() .setHeader(getHeader(PageMode.ALL_CLASSES)) .addMainContent(mainContent) .setFooter(getFooter())); - printHtmlDocument(null, "class index", bodyTree); + printHtmlDocument(null, "class index", body); } /** - * Add all types to the content tree. + * Add all types to the content. * - * @param content HtmlTree content to which the links will be added + * @param target the content to which the links will be added */ - protected void addContents(Content content) { + protected void addContents(Content target) { Table table = new Table(HtmlStyle.summaryTable) .setHeader(new TableHeader(contents.classLabel, contents.descriptionLabel)) .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast) .setId(HtmlIds.ALL_CLASSES_TABLE) .setDefaultTab(contents.allClassesAndInterfacesLabel) - .addTab(contents.interfaces, utils::isInterface) - .addTab(contents.classes, e -> utils.isOrdinaryClass((TypeElement)e)) + .addTab(contents.interfaces, utils::isPlainInterface) + .addTab(contents.classes, e -> utils.isNonThrowableClass((TypeElement)e)) .addTab(contents.enums, utils::isEnum) .addTab(contents.records, e -> utils.isRecord((TypeElement)e)) .addTab(contents.exceptionClasses, e -> utils.isThrowable((TypeElement)e)) - .addTab(contents.annotationTypes, utils::isAnnotationType); + .addTab(contents.annotationTypes, utils::isAnnotationInterface); for (Character unicode : indexBuilder.getFirstCharacters()) { for (IndexItem indexItem : indexBuilder.getItems(unicode)) { TypeElement typeElement = (TypeElement) indexItem.getElement(); @@ -131,12 +131,12 @@ public class AllClassesIndexWriter extends HtmlDocletWriter { } } Content titleContent = contents.allClassesAndInterfacesLabel; - Content pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, titleContent); - Content headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading); - content.add(headerDiv); + var headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading); + target.add(headerDiv); if (!table.isEmpty()) { - content.add(table); + target.add(table); if (table.needsScript()) { getMainBodyScript().append(table.getScript()); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java index f4ad3387b966ddd9b927f2bd3b7cff2c05ccae26..9c0ebe887ac285655a580e16bb0c03ab9bb5c5c7 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.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 @@ -76,24 +76,24 @@ public class AllPackagesIndexWriter extends HtmlDocletWriter { Content mainContent = new ContentBuilder(); addPackages(mainContent); Content titleContent = contents.allPackagesLabel; - Content pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, titleContent); - Content headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading); - HtmlTree bodyTree = getBody(getWindowTitle(label)); - bodyTree.add(new BodyContents() + var headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading); + HtmlTree body = getBody(getWindowTitle(label)); + body.add(new BodyContents() .setHeader(getHeader(PageMode.ALL_PACKAGES)) .addMainContent(headerDiv) .addMainContent(mainContent) .setFooter(getFooter())); - printHtmlDocument(null, "package index", bodyTree); + printHtmlDocument(null, "package index", body); } /** - * Add all the packages to the content tree. + * Add all the packages to the content. * - * @param content HtmlTree content to which the links will be added + * @param target the content to which the links will be added */ - protected void addPackages(Content content) { + protected void addPackages(Content target) { Table table = new Table(HtmlStyle.summaryTable) .setCaption(Text.of(contents.packageSummaryLabel.toString())) .setHeader(new TableHeader(contents.packageLabel, contents.descriptionLabel)) @@ -106,6 +106,6 @@ public class AllPackagesIndexWriter extends HtmlDocletWriter { table.addRow(pkg, packageLinkContent, summaryContent); } } - content.add(table); + target.add(table); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeMemberWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeMemberWriterImpl.java index 5ae2ffcf84ab20abda5c3607aafb2b6075b29fa5..5f7e4acec9fd00624683ed35b7f043255e84239e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeMemberWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeMemberWriterImpl.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 @@ -92,24 +92,24 @@ public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, - Content memberSummaryTree) { + Content content) { switch (kind) { - case OPTIONAL -> memberSummaryTree.add(selectComment( + case OPTIONAL -> content.add(selectComment( MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY, MarkerComments.START_OF_ANNOTATION_INTERFACE_OPTIONAL_MEMBER_SUMMARY)); - case REQUIRED -> memberSummaryTree.add(selectComment( + case REQUIRED -> content.add(selectComment( MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY, MarkerComments.START_OF_ANNOTATION_INTERFACE_REQUIRED_MEMBER_SUMMARY)); case ANY -> throw new UnsupportedOperationException("unsupported member kind"); } - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + Content c = new ContentBuilder(); + writer.addSummaryHeader(this, c); + return c; } @Override - public Content getMemberTreeHeader() { - return writer.getMemberTreeHeader(); + public Content getMemberHeader() { + return writer.getMemberHeader(); } @Override @@ -131,21 +131,21 @@ public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter } @Override - public Content getAnnotationDetailsTreeHeader() { - Content memberDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getAnnotationDetailsHeader() { + Content memberDetails = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.annotationTypeDetailsLabel); - memberDetailsTree.add(heading); - return memberDetailsTree; + memberDetails.add(heading); + return memberDetails; } @Override - public Content getAnnotationDocTreeHeader(Element member) { - Content annotationDocTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getAnnotationHeaderContent(Element member) { + Content content = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(name(member))); - annotationDocTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree) + content.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, content) .setId(htmlIds.forMember(typeElement, (ExecutableElement) member)); } @@ -158,40 +158,40 @@ public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter } @Override - public void addDeprecated(Element member, Content annotationDocTree) { - addDeprecatedInfo(member, annotationDocTree); + public void addDeprecated(Element member, Content target) { + addDeprecatedInfo(member, target); } @Override - public void addPreview(Element member, Content contentTree) { - addPreviewInfo(member, contentTree); + public void addPreview(Element member, Content content) { + addPreviewInfo(member, content); } @Override - public void addComments(Element member, Content annotationDocTree) { - addComment(member, annotationDocTree); + public void addComments(Element member, Content annotationContent) { + addComment(member, annotationContent); } @Override - public void addTags(Element member, Content annotationDocTree) { - writer.addTagsInfo(member, annotationDocTree); + public void addTags(Element member, Content annotationContent) { + writer.addTagsInfo(member, annotationContent); } @Override - public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree) { - Content annotationDetails = new ContentBuilder(annotationDetailsTreeHeader, annotationDetailsTree); - return getMemberTree(HtmlTree.SECTION(HtmlStyle.memberDetails, annotationDetails)); + public Content getAnnotationDetails(Content annotationDetailsHeader, Content annotationDetails) { + Content c = new ContentBuilder(annotationDetailsHeader, annotationDetails); + return getMember(HtmlTree.SECTION(HtmlStyle.memberDetails, c)); } @Override - public void addSummaryLabel(Content memberTree) { - HtmlTree label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, switch (kind) { case REQUIRED -> contents.annotateTypeRequiredMemberSummaryLabel; case OPTIONAL -> contents.annotateTypeOptionalMemberSummaryLabel; case ANY -> throw new UnsupportedOperationException("unsupported member kind"); }); - memberTree.add(label); + content.add(label); } /** @@ -227,27 +227,27 @@ public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { } @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member, - Content tdSummary) { + Content content) { Content memberLink = writer.getDocLink(context, utils.getEnclosingTypeElement(member), member, name(member), HtmlStyle.memberNameLink); - Content code = HtmlTree.CODE(memberLink); - tdSummary.add(code); + var code = HtmlTree.CODE(memberLink); + content.add(code); } @Override protected void addInheritedSummaryLink(TypeElement typeElement, - Element member, Content linksTree) { + Element member, Content target) { //Not applicable. } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { - addModifierAndType(member, getType(member), tdSummaryType); + protected void addSummaryType(Element member, Content content) { + addModifiersAndType(member, getType(member), content); } @Override @@ -268,15 +268,15 @@ public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter : member.asType(); } - public void addDefaultValueInfo(Element member, Content annotationDocTree) { - if (utils.isAnnotationType(member)) { + public void addDefaultValueInfo(Element member, Content annotationContent) { + if (utils.isAnnotationInterface(member.getEnclosingElement())) { ExecutableElement ee = (ExecutableElement) member; AnnotationValue value = ee.getDefaultValue(); if (value != null) { - Content dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.default_)); dl.add(HtmlTree.DD(Text.of(value.toString()))); - annotationDocTree.add(dl); + annotationContent.add(dl); } } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java index 840676e875cab6ec486a4f948ddd24605c8e2004..cbc12cc09a8ede3e97c1c7efe6ce6e3e7b880ece 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java @@ -230,24 +230,24 @@ public class ClassUseWriter extends SubWriterHolderWriter { /** * Add the class use documentation. * - * @param contentTree the content tree to which the class use information will be added + * @param content the content to which the class use information will be added */ - protected void addClassUse(Content contentTree) { - Content content = new ContentBuilder(); + protected void addClassUse(Content content) { + Content c = new ContentBuilder(); if (configuration.packages.size() > 1) { - addPackageList(content); - addPackageAnnotationList(content); + addPackageList(c); + addPackageAnnotationList(c); } - addClassList(content); - contentTree.add(content); + addClassList(c); + content.add(c); } /** * Add the packages elements that use the given class. * - * @param contentTree the content tree to which the packages elements will be added + * @param content the content to which the packages elements will be added */ - protected void addPackageList(Content contentTree) { + protected void addPackageList(Content content) { Content caption = contents.getContent( "doclet.ClassUse_Packages.that.use.0", getLink(new HtmlLinkInfo(configuration, @@ -259,16 +259,16 @@ public class ClassUseWriter extends SubWriterHolderWriter { for (PackageElement pkg : pkgSet) { addPackageUse(pkg, table); } - contentTree.add(table); + content.add(table); } /** * Add the package annotation elements. * - * @param contentTree the content tree to which the package annotation elements will be added + * @param content the content to which the package annotation elements will be added */ - protected void addPackageAnnotationList(Content contentTree) { - if (!utils.isAnnotationType(typeElement) || + protected void addPackageAnnotationList(Content content) { + if (!utils.isAnnotationInterface(typeElement) || pkgToPackageAnnotations == null || pkgToPackageAnnotations.isEmpty()) { return; @@ -287,30 +287,30 @@ public class ClassUseWriter extends SubWriterHolderWriter { addSummaryComment(pkg, summary); table.addRow(getPackageLink(pkg, getLocalizedPackageName(pkg)), summary); } - contentTree.add(table); + content.add(table); } /** * Add the class elements that use the given class. * - * @param contentTree the content tree to which the class elements will be added + * @param content the content to which the class elements will be added */ - protected void addClassList(Content contentTree) { - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList); + protected void addClassList(Content content) { + var ul = HtmlTree.UL(HtmlStyle.blockList); for (PackageElement pkg : pkgSet) { - HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.detail) + var section = HtmlTree.SECTION(HtmlStyle.detail) .setId(htmlIds.forPackage(pkg)); Content link = contents.getContent("doclet.ClassUse_Uses.of.0.in.1", getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement)), getPackageLink(pkg, getLocalizedPackageName(pkg))); - Content heading = HtmlTree.HEADING(Headings.TypeUse.SUMMARY_HEADING, link); - htmlTree.add(heading); - addClassUse(pkg, htmlTree); - ul.add(HtmlTree.LI(htmlTree)); + var heading = HtmlTree.HEADING(Headings.TypeUse.SUMMARY_HEADING, link); + section.add(heading); + addClassUse(pkg, section); + ul.add(HtmlTree.LI(section)); } - Content li = HtmlTree.SECTION(HtmlStyle.classUses, ul); - contentTree.add(li); + var li = HtmlTree.SECTION(HtmlStyle.classUses, ul); + content.add(li); } /** @@ -331,81 +331,81 @@ public class ClassUseWriter extends SubWriterHolderWriter { * Add the class use information. * * @param pkg the package that uses the given class - * @param contentTree the content tree to which the class use information will be added + * @param content the content to which the class use information will be added */ - protected void addClassUse(PackageElement pkg, Content contentTree) { + protected void addClassUse(PackageElement pkg, Content content) { Content classLink = getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement)); Content pkgLink = getPackageLink(pkg, getLocalizedPackageName(pkg)); classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg), contents.getContent("doclet.ClassUse_Annotation", classLink, - pkgLink), contentTree); + pkgLink), content); classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_TypeParameter", classLink, - pkgLink), contentTree); + pkgLink), content); classSubWriter.addUseInfo(pkgToSubclass.get(pkg), contents.getContent("doclet.ClassUse_Subclass", classLink, - pkgLink), contentTree); + pkgLink), content); classSubWriter.addUseInfo(pkgToSubinterface.get(pkg), contents.getContent("doclet.ClassUse_Subinterface", classLink, - pkgLink), contentTree); + pkgLink), content); classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg), contents.getContent("doclet.ClassUse_ImplementingClass", classLink, - pkgLink), contentTree); + pkgLink), content); fieldSubWriter.addUseInfo(pkgToField.get(pkg), contents.getContent("doclet.ClassUse_Field", classLink, - pkgLink), contentTree); + pkgLink), content); fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg), contents.getContent("doclet.ClassUse_FieldAnnotations", classLink, - pkgLink), contentTree); + pkgLink), content); fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_FieldTypeParameter", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg), contents.getContent("doclet.ClassUse_MethodAnnotations", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg), contents.getContent("doclet.ClassUse_MethodParameterAnnotations", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_MethodTypeParameter", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg), contents.getContent("doclet.ClassUse_MethodReturn", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_MethodReturnTypeParameter", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg), contents.getContent("doclet.ClassUse_MethodArgs", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_MethodArgsTypeParameters", classLink, - pkgLink), contentTree); + pkgLink), content); methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg), contents.getContent("doclet.ClassUse_MethodThrows", classLink, - pkgLink), contentTree); + pkgLink), content); constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg), contents.getContent("doclet.ClassUse_ConstructorAnnotations", classLink, - pkgLink), contentTree); + pkgLink), content); constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg), contents.getContent("doclet.ClassUse_ConstructorParameterAnnotations", classLink, - pkgLink), contentTree); + pkgLink), content); constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg), contents.getContent("doclet.ClassUse_ConstructorArgs", classLink, - pkgLink), contentTree); + pkgLink), content); constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg), contents.getContent("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, - pkgLink), contentTree); + pkgLink), content); constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg), contents.getContent("doclet.ClassUse_ConstructorThrows", classLink, - pkgLink), contentTree); + pkgLink), content); } /** - * Get the header for the class use Listing. + * Get the header for the class use listing. * - * @return a content tree representing the class use header + * @return the class use header */ protected HtmlTree getClassUseHeader() { String cltype = resources.getText(switch (typeElement.getKind()) { @@ -418,16 +418,16 @@ public class ClassUseWriter extends SubWriterHolderWriter { String clname = utils.getFullyQualifiedName(typeElement); String title = resources.getText("doclet.Window_ClassUse_Header", cltype, clname); - HtmlTree bodyTree = getBody(getWindowTitle(title)); + HtmlTree body = getBody(getWindowTitle(title)); ContentBuilder headingContent = new ContentBuilder(); headingContent.add(contents.getContent("doclet.ClassUse_Title", cltype)); headingContent.add(new HtmlTree(TagName.BR)); headingContent.add(clname); - Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, headingContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); bodyContents.setHeader(getHeader(PageMode.USE, typeElement)).addMainContent(div); - return bodyTree; + return body; } @Override 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 45b10dc89e16241d7c5519a26b94d211c98487e0..02f3530ecb60d7ac8650b4e69bdbabbdbfa0db35 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 @@ -27,7 +27,6 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Set; import java.util.SortedSet; @@ -68,10 +67,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; * deletion without notice. * * @see javax.lang.model.element.TypeElement - * @see java.util.Collections - * @see java.util.List - * @see java.util.ArrayList - * @see java.util.HashMap */ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter { @@ -104,12 +99,12 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite @Override public Content getHeader(String header) { - HtmlTree bodyTree = getBody(getWindowTitle(utils.getSimpleName(typeElement))); - HtmlTree div = HtmlTree.DIV(HtmlStyle.header); + HtmlTree body = getBody(getWindowTitle(utils.getSimpleName(typeElement))); + var div = HtmlTree.DIV(HtmlStyle.header); if (configuration.showModules) { ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); - Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel); - Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); + var classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel); + var moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); moduleNameDiv.add(Entity.NO_BREAK_SPACE); moduleNameDiv.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName()))); @@ -117,8 +112,8 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } PackageElement pkg = utils.containingPackage(typeElement); if (!pkg.isUnnamed()) { - Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel); - Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); + var classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel); + var pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); pkgNameDiv.add(Entity.NO_BREAK_SPACE); Content pkgNameContent = getPackageLink(pkg, getLocalizedPackageName(pkg)); pkgNameDiv.add(pkgNameContent); @@ -128,14 +123,14 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite HtmlLinkInfo.Kind.CLASS_HEADER, typeElement); //Let's not link to ourselves in the header. linkInfo.linkToSelf = false; - Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, Text.of(header)); heading.add(getTypeParameterLinks(linkInfo)); div.add(heading); bodyContents.setHeader(getHeader(PageMode.CLASS, typeElement)) .addMainContent(MarkerComments.START_OF_CLASS_DATA) .addMainContent(div); - return bodyTree; + return body; } @Override @@ -169,23 +164,18 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } @Override - public void printDocument(Content contentTree) throws DocFileIOException { + public void printDocument(Content content) throws DocFileIOException { String description = getDescription("declaration", typeElement); PackageElement pkg = utils.containingPackage(typeElement); List localStylesheets = getLocalStylesheets(pkg); - contentTree.add(bodyContents); + content.add(bodyContents); printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement), - description, localStylesheets, contentTree); + description, localStylesheets, content); } @Override - public Content getClassInfoTreeHeader() { - return getMemberTreeHeader(); - } - - @Override - public Content getClassInfo(Content classInfoTree) { - return getMemberTree(HtmlIds.CLASS_DESCRIPTION, HtmlStyle.classDescription, classInfoTree); + public Content getClassInfo(Content classInfo) { + return getMember(HtmlIds.CLASS_DESCRIPTION, HtmlStyle.classDescription, classInfo); } @Override @@ -194,51 +184,51 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } @Override - public void addClassSignature(Content classInfoTree) { - classInfoTree.add(new HtmlTree(TagName.HR)); - classInfoTree.add(new Signatures.TypeSignature(typeElement, this) + public void addClassSignature(Content classInfo) { + classInfo.add(new HtmlTree(TagName.HR)); + classInfo.add(new Signatures.TypeSignature(typeElement, this) .toContent()); } @Override - public void addClassDescription(Content classInfoTree) { - addPreviewInfo(classInfoTree); + public void addClassDescription(Content classInfo) { + addPreviewInfo(classInfo); if (!options.noComment()) { // generate documentation for the class. if (!utils.getFullBody(typeElement).isEmpty()) { - addInlineComment(typeElement, classInfoTree); + addInlineComment(typeElement, classInfo); } } } - private void addPreviewInfo(Content classInfoTree) { - addPreviewInfo(typeElement, classInfoTree); + private void addPreviewInfo(Content content) { + addPreviewInfo(typeElement, content); } @Override - public void addClassTagInfo(Content classInfoTree) { + public void addClassTagInfo(Content classInfo) { if (!options.noComment()) { // Print Information about all the tags here - addTagsInfo(typeElement, classInfoTree); + addTagsInfo(typeElement, classInfo); } } /** - * Get the class hierarchy tree for the given class. + * Get the class inheritance tree for the given class. * - * @param type the class to print the hierarchy for - * @return a content tree for class inheritance + * @param type the class to get the inheritance tree for + * @return the class inheritance tree */ - private Content getClassInheritanceTree(TypeMirror type) { + private Content getClassInheritanceTreeContent(TypeMirror type) { TypeMirror sup; HtmlTree classTree = null; do { sup = utils.getFirstVisibleSuperClass(type); - HtmlTree htmlElement = HtmlTree.DIV(HtmlStyle.inheritance, getTreeForClassHelper(type)); + var entry = HtmlTree.DIV(HtmlStyle.inheritance, getClassHelperContent(type)); if (classTree != null) - htmlElement.add(classTree); - classTree = htmlElement; + entry.add(classTree); + classTree = entry; type = sup; } while (sup != null); classTree.put(HtmlAttr.TITLE, contents.getContent("doclet.Inheritance_Tree").toString()); @@ -246,54 +236,54 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } /** - * Get the class helper tree for the given class. + * Get the class helper for the given class. * - * @param type the class to print the helper for - * @return a content tree for class helper + * @param type the class to get the helper for + * @return the class helper */ - private Content getTreeForClassHelper(TypeMirror type) { - Content content = new ContentBuilder(); + private Content getClassHelperContent(TypeMirror type) { + Content result = new ContentBuilder(); if (utils.typeUtils.isSameType(type, typeElement.asType())) { Content typeParameters = getTypeParameterLinks( new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.TREE, typeElement)); if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { - content.add(utils.asTypeElement(type).getSimpleName()); - content.add(typeParameters); + result.add(utils.asTypeElement(type).getSimpleName()); + result.add(typeParameters); } else { - content.add(utils.asTypeElement(type).getQualifiedName()); - content.add(typeParameters); + result.add(utils.asTypeElement(type).getQualifiedName()); + result.add(typeParameters); } } else { Content link = getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS_TREE_PARENT, type) .label(configuration.getClassName(utils.asTypeElement(type)))); - content.add(link); + result.add(link); } - return content; + return result; } @Override - public void addClassTree(Content classContentTree) { + public void addClassTree(Content target) { if (!utils.isClass(typeElement)) { return; } - classContentTree.add(getClassInheritanceTree(typeElement.asType())); + target.add(getClassInheritanceTreeContent(typeElement.asType())); } @Override - public void addParamInfo(Content classInfoTree) { + public void addParamInfo(Content target) { if (utils.hasBlockTag(typeElement, DocTree.Kind.PARAM)) { Content paramInfo = (new ParamTaglet()).getAllBlockTagOutput(typeElement, getTagletWriterInstance(false)); if (!paramInfo.isEmpty()) { - classInfoTree.add(HtmlTree.DL(HtmlStyle.notes, paramInfo)); + target.add(HtmlTree.DL(HtmlStyle.notes, paramInfo)); } } } @Override - public void addSubClassInfo(Content classInfoTree) { + public void addSubClassInfo(Content target) { if (utils.isClass(typeElement)) { for (String s : suppressSubtypesSet) { if (typeElement.getQualifiedName().contentEquals(s)) { @@ -302,30 +292,30 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } Set subclasses = classtree.directSubClasses(typeElement, false); if (!subclasses.isEmpty()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.subclassesLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUBCLASSES, subclasses))); - classInfoTree.add(dl); + target.add(dl); } } } @Override - public void addSubInterfacesInfo(Content classInfoTree) { - if (utils.isInterface(typeElement)) { + public void addSubInterfacesInfo(Content target) { + if (utils.isPlainInterface(typeElement)) { Set subInterfaces = classtree.allSubClasses(typeElement, false); if (!subInterfaces.isEmpty()) { - Content dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.subinterfacesLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUBINTERFACES, subInterfaces))); - classInfoTree.add(dl); + target.add(dl); } } } @Override - public void addInterfaceUsageInfo (Content classInfoTree) { - if (!utils.isInterface(typeElement)) { + public void addInterfaceUsageInfo(Content target) { + if (!utils.isPlainInterface(typeElement)) { return; } for (String s : suppressImplementingSet) { @@ -335,67 +325,67 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite } Set implcl = classtree.implementingClasses(typeElement); if (!implcl.isEmpty()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.implementingClassesLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.IMPLEMENTED_CLASSES, implcl))); - classInfoTree.add(dl); + target.add(dl); } } @Override - public void addImplementedInterfacesInfo(Content classInfoTree) { + public void addImplementedInterfacesInfo(Content target) { SortedSet interfaces = new TreeSet<>(comparators.makeTypeMirrorClassUseComparator()); interfaces.addAll(utils.getAllInterfaces(typeElement)); if (utils.isClass(typeElement) && !interfaces.isEmpty()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.allImplementedInterfacesLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.IMPLEMENTED_INTERFACES, interfaces))); - classInfoTree.add(dl); + target.add(dl); } } @Override - public void addSuperInterfacesInfo(Content classInfoTree) { + public void addSuperInterfacesInfo(Content target) { SortedSet interfaces = new TreeSet<>(comparators.makeTypeMirrorIndexUseComparator()); interfaces.addAll(utils.getAllInterfaces(typeElement)); - if (utils.isInterface(typeElement) && !interfaces.isEmpty()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + if (utils.isPlainInterface(typeElement) && !interfaces.isEmpty()) { + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.allSuperinterfacesLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUPER_INTERFACES, interfaces))); - classInfoTree.add(dl); + target.add(dl); } } @Override - public void addNestedClassInfo(final Content classInfoTree) { + public void addNestedClassInfo(final Content target) { Element outerClass = typeElement.getEnclosingElement(); if (outerClass == null) return; new SimpleElementVisitor8() { @Override public Void visitType(TypeElement e, Void p) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); - dl.add(HtmlTree.DT(utils.isInterface(e) + var dl = HtmlTree.DL(HtmlStyle.notes); + dl.add(HtmlTree.DT(utils.isPlainInterface(e) ? contents.enclosingInterfaceLabel : contents.enclosingClassLabel)); dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.CLASS, List.of(e)))); - classInfoTree.add(dl); + target.add(dl); return null; } }.visit(outerClass); } @Override - public void addFunctionalInterfaceInfo (Content classInfoTree) { + public void addFunctionalInterfaceInfo (Content target) { if (isFunctionalInterface()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(HtmlTree.DT(contents.functionalInterface)); - Content dd = new HtmlTree(TagName.DD); + var dd = new HtmlTree(TagName.DD); dd.add(contents.functionalInterfaceMessage); dl.add(dd); - classInfoTree.add(dl); + target.add(dl); } } @@ -411,11 +401,11 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite @Override - public void addClassDeprecationInfo(Content classInfoTree) { + public void addClassDeprecationInfo(Content classInfo) { List deprs = utils.getDeprecatedTrees(typeElement); if (utils.isDeprecated(typeElement)) { - Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(typeElement)); - Content div = HtmlTree.DIV(HtmlStyle.deprecationBlock, deprLabel); + var deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(typeElement)); + var div = HtmlTree.DIV(HtmlStyle.deprecationBlock, deprLabel); if (!deprs.isEmpty()) { CommentHelper ch = utils.getCommentHelper(typeElement); DocTree dt = deprs.get(0); @@ -424,16 +414,16 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite addInlineDeprecatedComment(typeElement, deprs.get(0), div); } } - classInfoTree.add(div); + classInfo.add(div); } } /** - * Get links to the given classes. + * Get the links to the given classes. * - * @param context the id of the context where the link will be printed - * @param list the list of classes - * @return a content tree for the class list + * @param context the id of the context where the links will be added + * @param list the classes + * @return the links */ private Content getClassLinks(HtmlLinkInfo.Kind context, Collection list) { Content content = new ContentBuilder(); @@ -468,16 +458,11 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite return typeElement; } - /** - * Get the member details tree - * - * @param contentTree the tree used to generate the member details tree - * @return a content tree for the member details - */ - public Content getMemberDetailsTree(Content contentTree) { - HtmlTree section = HtmlTree.SECTION(HtmlStyle.details, contentTree); + @Override + public Content getMemberDetails(Content content) { + var section = HtmlTree.SECTION(HtmlStyle.details, content); // The following id is required by the Navigation bar - if (utils.isAnnotationType(typeElement)) { + if (utils.isAnnotationInterface(typeElement)) { section.setId(HtmlIds.ANNOTATION_TYPE_ELEMENT_DETAIL); } return section; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java index 1723bc6ecfd5a93650116abae9618c3b4c8947ef..b6c4cbc874dab43e368ed9c92fea8b331028ed32 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -68,9 +68,9 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons private final TableHeader constantsTableHeader; /** - * The HTML tree for constant values summary. + * The HTML tree for constant values summary currently being written. */ - private HtmlTree summaryTree; + private HtmlTree summarySection; private final BodyContents bodyContents = new BodyContents(); @@ -91,9 +91,9 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons @Override public Content getHeader() { String label = resources.getText("doclet.Constants_Summary"); - HtmlTree bodyTree = getBody(getWindowTitle(label)); + HtmlTree body = getBody(getWindowTitle(label)); bodyContents.setHeader(getHeader(PageMode.CONSTANT_VALUES)); - return bodyTree; + return body; } @Override @@ -103,7 +103,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons @Override public void addLinkToPackageContent(PackageElement pkg, - Set printedPackageHeaders, Content contentListTree) { + Set printedPackageHeaders, Content content) { //add link to summary Content link; if (pkg.isUnnamed()) { @@ -117,20 +117,20 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(pkg); printedPackageHeaders.add(abbrevPkg); } - contentListTree.add(HtmlTree.LI(link)); + content.add(HtmlTree.LI(link)); } @Override - public void addContentsList(Content contentListTree) { + public void addContentsList(Content content) { Content titleContent = contents.constantsSummaryTitle; - Content pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var pHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, titleContent); - Content div = HtmlTree.DIV(HtmlStyle.header, pHeading); + var div = HtmlTree.DIV(HtmlStyle.header, pHeading); Content headingContent = contents.contentsHeading; - Content heading = HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, headingContent); - HtmlTree section = HtmlTree.SECTION(HtmlStyle.packages, heading); - section.add(contentListTree); + var section = HtmlTree.SECTION(HtmlStyle.packages, heading); + section.add(content); div.add(section); bodyContents.addMainContent(div); } @@ -141,11 +141,11 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons } @Override - public void addPackageName(PackageElement pkg, Content summariesTree, boolean first) { + public void addPackageName(PackageElement pkg, Content toContent, boolean first) { Content pkgNameContent; HtmlId anchorName; if (!first) { - summariesTree.add(summaryTree); + toContent.add(summarySection); } if (pkg.isUnnamed()) { anchorName = HtmlIds.UNNAMED_PACKAGE_ANCHOR; @@ -155,11 +155,11 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons anchorName = htmlIds.forPackage(pkg); pkgNameContent = getPackageLabel(parsedPackageName); } - Content headingContent = Text.of(".*"); - Content heading = HtmlTree.HEADING_TITLE(Headings.ConstantsSummary.PACKAGE_HEADING, + var headingContent = Text.of(".*"); + var heading = HtmlTree.HEADING_TITLE(Headings.ConstantsSummary.PACKAGE_HEADING, pkgNameContent); heading.add(headingContent); - summaryTree = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading) + summarySection = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading) .setId(anchorName); } @@ -169,14 +169,14 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons } @Override - public void addClassConstant(Content summariesTree, Content classConstantTree) { - summaryTree.add(classConstantTree); + public void addClassConstant(Content fromClassConstant) { + summarySection.add(fromClassConstant); hasConstants = true; } @Override public void addConstantMembers(TypeElement typeElement, Collection fields, - Content classConstantTree) { + Content target) { currentTypeElement = typeElement; //generate links backward only to public classes. @@ -201,7 +201,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons for (VariableElement field : fields) { table.addRow(getTypeColumn(field), getNameColumn(field), getValue(field)); } - classConstantTree.add(HtmlTree.LI(table)); + target.add(HtmlTree.LI(table)); } /** @@ -212,7 +212,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons */ private Content getTypeColumn(VariableElement member) { Content typeContent = new ContentBuilder(); - Content code = new HtmlTree(TagName.CODE) + var code = new HtmlTree(TagName.CODE) .setId(htmlIds.forMember(currentTypeElement, member)); for (Modifier mod : member.getModifiers()) { code.add(Text.of(mod.toString())) @@ -249,11 +249,11 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons } @Override - public void addConstantSummaries(Content summariesTree) { - if (summaryTree != null) { - summariesTree.add(summaryTree); + public void addConstantSummaries(Content content) { + if (summarySection != null) { + content.add(summarySection); } - bodyContents.addMainContent(summariesTree); + bodyContents.addMainContent(content); } @Override @@ -262,9 +262,9 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons } @Override - public void printDocument(Content contentTree) throws DocFileIOException { - contentTree.add(bodyContents); - printHtmlDocument(null, "summary of constants", contentTree); + public void printDocument(Content content) throws DocFileIOException { + content.add(bodyContents); + printHtmlDocument(null, "summary of constants", content); if (hasConstants && configuration.mainIndex != null) { configuration.mainIndex.add(IndexItem.of(IndexItem.Category.TAGS, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java index ed5c0220732ce888758b74586fed8a12ad1dd5cd..7be2f2da5a10742403a2ea838570ee8dbaec527c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.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 @@ -90,11 +90,11 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, - Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_CONSTRUCTOR_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + Content content) { + content.add(MarkerComments.START_OF_CONSTRUCTOR_SUMMARY); + Content c = new ContentBuilder(); + writer.addSummaryHeader(this, c); + return c; } @Override @@ -104,26 +104,26 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter } @Override - public Content getConstructorDetailsTreeHeader(Content memberDetailsTree) { - memberDetailsTree.add(MarkerComments.START_OF_CONSTRUCTOR_DETAILS); - Content constructorDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getConstructorDetailsHeader(Content content) { + content.add(MarkerComments.START_OF_CONSTRUCTOR_DETAILS); + Content constructorDetails = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.constructorDetailsLabel); - constructorDetailsTree.add(heading); - return constructorDetailsTree; + constructorDetails.add(heading); + return constructorDetails; } @Override - public Content getConstructorDocTreeHeader(ExecutableElement constructor) { - Content constructorDocTree = new ContentBuilder(); - HtmlTree heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getConstructorHeaderContent(ExecutableElement constructor) { + Content content = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(name(constructor))); HtmlId erasureAnchor = htmlIds.forErasure(constructor); if (erasureAnchor != null) { heading.setId(erasureAnchor); } - constructorDocTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, constructorDocTree) + content.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, content) .setId(htmlIds.forMember(constructor)); } @@ -137,32 +137,32 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter } @Override - public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) { - addDeprecatedInfo(constructor, constructorDocTree); + public void addDeprecated(ExecutableElement constructor, Content constructorContent) { + addDeprecatedInfo(constructor, constructorContent); } @Override - public void addPreview(ExecutableElement constructor, Content constructorDocTree) { - addPreviewInfo(constructor, constructorDocTree); + public void addPreview(ExecutableElement constructor, Content content) { + addPreviewInfo(constructor, content); } @Override - public void addComments(ExecutableElement constructor, Content constructorDocTree) { - addComment(constructor, constructorDocTree); + public void addComments(ExecutableElement constructor, Content constructorContent) { + addComment(constructor, constructorContent); } @Override - public void addTags(ExecutableElement constructor, Content constructorDocTree) { - writer.addTagsInfo(constructor, constructorDocTree); + public void addTags(ExecutableElement constructor, Content constructorContent) { + writer.addTagsInfo(constructor, constructorContent); } @Override - public Content getConstructorDetails(Content constructorDetailsTreeHeader, Content constructorDetailsTree) { + public Content getConstructorDetails(Content memberDetailsHeader, Content memberDetails) { return writer.getDetailsListItem( HtmlTree.SECTION(HtmlStyle.constructorDetails) .setId(HtmlIds.CONSTRUCTOR_DETAIL) - .add(constructorDetailsTreeHeader) - .add(constructorDetailsTree)); + .add(memberDetailsHeader) + .add(memberDetails)); } @Override @@ -171,10 +171,10 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.constructorSummaryLabel); - memberTree.add(label); + content.add(label); } @Override @@ -206,13 +206,13 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { + protected void addSummaryType(Element member, Content content) { if (foundNonPubConstructor) { - Content code = new HtmlTree(TagName.CODE); + var code = new HtmlTree(TagName.CODE); if (utils.isProtected(member)) { code.add("protected "); } else if (utils.isPrivate(member)) { @@ -223,12 +223,12 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter code.add( resources.getText("doclet.Package_private")); } - tdSummaryType.add(code); + content.add(code); } } @Override - public Content getMemberTreeHeader(){ - return writer.getMemberTreeHeader(); + public Content getMemberHeader(){ + return writer.getMemberHeader(); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java index 1b18aa4293c2ee1d2bf08d2e74324652612573a5..1c0be973c307f119f678b2c900c54c4c521e0551 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.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 @@ -343,7 +343,7 @@ public class Contents { * a given key in the doclet's resources. * * @param key the key for the desired string - * @return a content tree for the string + * @return the string */ public Content getContent(String key) { return Text.of(resources.getText(key)); @@ -356,7 +356,7 @@ public class Contents { * * @param key the key for the desired string * @param o0 string or content argument to be formatted into the result - * @return a content tree for the text + * @return the string */ public Content getContent(String key, Object o0) { return getContent(key, o0, null, null); @@ -370,7 +370,7 @@ public class Contents { * @param key the key for the desired string * @param o0 string or content argument to be formatted into the result * @param o1 string or content argument to be formatted into the result - * @return a content tree for the text + * @return the string */ public Content getContent(String key, Object o0, Object o1) { return getContent(key, o0, o1, null); @@ -385,7 +385,7 @@ public class Contents { * @param o0 string or content argument to be formatted into the result * @param o1 string or content argument to be formatted into the result * @param o2 string or content argument to be formatted into the result - * @return a content tree for the text + * @return the string */ public Content getContent(String key, Object o0, Object o1, Object o2) { Content c = new ContentBuilder(); @@ -423,7 +423,7 @@ public class Contents { * * @param separator the separator * @param items the items - * @return the content + * @return the composition */ public Content join(Content separator, Collection items) { Content result = new ContentBuilder(); @@ -446,7 +446,7 @@ public class Contents { * the named resource string. * * @param key the key for the desired string - * @return a content tree for the string + * @return the string */ private Content getNonBreakResource(String key) { return getNonBreakString(resources.getText(key)); @@ -458,7 +458,7 @@ public class Contents { * the named resource string. * * @param text the string - * @return a content tree for the string + * @return the string content */ public Content getNonBreakString(String text) { Content c = new ContentBuilder(); @@ -474,9 +474,9 @@ public class Contents { } /** - * Returns a content for a visible member kind. + * {@return a label that describes the VisibleMemberTable kind} + * * @param kind the visible member table kind. - * @return the string content */ public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) { return Objects.requireNonNull(navLinkLabels.get(kind)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java index 652e53a3075f71bfec9926689a8d58568d02e654..ba1e5eb001358ef723d3ae375b962a66c77b0261 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.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 @@ -52,7 +52,6 @@ import javax.tools.JavaFileManager.Location; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; @@ -213,7 +212,7 @@ public class DocFilesHandlerImpl implements DocFilesHandler { .setHeader(docletWriter.getHeader(PageMode.DOC_FILE, element)) .addMainContent(pageContent) .setFooter(docletWriter.getFooter())); - docletWriter.printHtmlDocument(Collections.emptyList(), null, localTagsContent, Collections.emptyList(), htmlContent); + docletWriter.printHtmlDocument(List.of(), null, localTagsContent, List.of(), htmlContent); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java index 3fbd13d0189e004246efe1345a82c7ec9ac8a08c..2c659e127b3931d79676727f1820af651134d8bc 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.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,11 +59,11 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, - Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_ENUM_CONSTANT_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + Content content) { + content.add(MarkerComments.START_OF_ENUM_CONSTANT_SUMMARY); + Content memberContent = new ContentBuilder(); + writer.addSummaryHeader(this, memberContent); + return memberContent; } @Override @@ -73,24 +73,24 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter } @Override - public Content getEnumConstantsDetailsTreeHeader(TypeElement typeElement, - Content memberDetailsTree) { - memberDetailsTree.add(MarkerComments.START_OF_ENUM_CONSTANT_DETAILS); - Content enumConstantsDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getEnumConstantsDetailsHeader(TypeElement typeElement, + Content memberDetails) { + memberDetails.add(MarkerComments.START_OF_ENUM_CONSTANT_DETAILS); + var enumConstantsDetailsContent = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.enumConstantDetailLabel); - enumConstantsDetailsTree.add(heading); - return enumConstantsDetailsTree; + enumConstantsDetailsContent.add(heading); + return enumConstantsDetailsContent; } @Override - public Content getEnumConstantsTreeHeader(VariableElement enumConstant, - Content enumConstantsDetailsTree) { - Content enumConstantsTree = new ContentBuilder(); - HtmlTree heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getEnumConstantsHeader(VariableElement enumConstant, + Content enumConstantsDetails) { + Content enumConstantsContent = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(name(enumConstant))); - enumConstantsTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, enumConstantsTree) + enumConstantsContent.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, enumConstantsContent) .setId(htmlIds.forMember(enumConstant)); } @@ -103,40 +103,40 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter } @Override - public void addDeprecated(VariableElement enumConstant, Content enumConstantsTree) { - addDeprecatedInfo(enumConstant, enumConstantsTree); + public void addDeprecated(VariableElement enumConstant, Content content) { + addDeprecatedInfo(enumConstant, content); } @Override - public void addPreview(VariableElement enumConstant, Content enumConstantsTree) { - addPreviewInfo(enumConstant, enumConstantsTree); + public void addPreview(VariableElement enumConstant, Content content) { + addPreviewInfo(enumConstant, content); } @Override - public void addComments(VariableElement enumConstant, Content enumConstantsTree) { - addComment(enumConstant, enumConstantsTree); + public void addComments(VariableElement enumConstant, Content enumConstants) { + addComment(enumConstant, enumConstants); } @Override - public void addTags(VariableElement enumConstant, Content enumConstantsTree) { - writer.addTagsInfo(enumConstant, enumConstantsTree); + public void addTags(VariableElement enumConstant, Content content) { + writer.addTagsInfo(enumConstant, content); } @Override - public Content getEnumConstantsDetails(Content enumConstantsDetailsTreeHeader, - Content enumConstantsDetailsTree) { + public Content getEnumConstantsDetails(Content memberDetailsHeader, + Content content) { return writer.getDetailsListItem( HtmlTree.SECTION(HtmlStyle.constantDetails) .setId(HtmlIds.ENUM_CONSTANT_DETAIL) - .add(enumConstantsDetailsTreeHeader) - .add(enumConstantsDetailsTree)); + .add(memberDetailsHeader) + .add(content)); } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.enumConstantSummary); - memberTree.add(label); + content.add(label); } @Override @@ -153,24 +153,24 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { } @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member, - Content tdSummary) { + Content content) { Content memberLink = writer.getDocLink(context, utils.getEnclosingTypeElement(member), member, name(member), HtmlStyle.memberNameLink); - Content code = HtmlTree.CODE(memberLink); - tdSummary.add(code); + var code = HtmlTree.CODE(memberLink); + content.add(code); } @Override - protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content target) { } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { + protected void addSummaryType(Element member, Content content) { //Not applicable. } @@ -181,7 +181,7 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter } @Override - public Content getMemberTreeHeader(){ - return writer.getMemberTreeHeader(); + public Content getMemberHeader(){ + return writer.getMemberHeader(); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java index 2402c18608d828681cf2d856ce7a6c7c197de427..acbc4aac321ad2d06fc51c50db2d8d64097d4719 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.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 @@ -62,11 +62,11 @@ public class FieldWriterImpl extends AbstractMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, - Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_FIELD_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + Content content) { + content.add(MarkerComments.START_OF_FIELD_SUMMARY); + Content memberContent = new ContentBuilder(); + writer.addSummaryHeader(this, memberContent); + return memberContent; } @Override @@ -76,22 +76,22 @@ public class FieldWriterImpl extends AbstractMemberWriter } @Override - public Content getFieldDetailsTreeHeader(Content memberDetailsTree) { - memberDetailsTree.add(MarkerComments.START_OF_FIELD_DETAILS); - Content fieldDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getFieldDetailsHeader(Content content) { + content.add(MarkerComments.START_OF_FIELD_DETAILS); + Content fieldDetailsContent = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.fieldDetailsLabel); - fieldDetailsTree.add(heading); - return fieldDetailsTree; + fieldDetailsContent.add(heading); + return fieldDetailsContent; } @Override - public Content getFieldDocTreeHeader(VariableElement field) { - Content fieldTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getFieldHeaderContent(VariableElement field) { + Content content = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(name(field))); - fieldTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, fieldTree) + content.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, content) .setId(htmlIds.forMember(field)); } @@ -104,41 +104,41 @@ public class FieldWriterImpl extends AbstractMemberWriter } @Override - public void addDeprecated(VariableElement field, Content fieldTree) { - addDeprecatedInfo(field, fieldTree); + public void addDeprecated(VariableElement field, Content fieldContent) { + addDeprecatedInfo(field, fieldContent); } @Override - public void addPreview(VariableElement field, Content fieldTree) { - addPreviewInfo(field, fieldTree); + public void addPreview(VariableElement field, Content content) { + addPreviewInfo(field, content); } @Override - public void addComments(VariableElement field, Content fieldTree) { + public void addComments(VariableElement field, Content fieldContent) { if (!utils.getFullBody(field).isEmpty()) { - writer.addInlineComment(field, fieldTree); + writer.addInlineComment(field, fieldContent); } } @Override - public void addTags(VariableElement field, Content fieldTree) { - writer.addTagsInfo(field, fieldTree); + public void addTags(VariableElement field, Content fieldContent) { + writer.addTagsInfo(field, fieldContent); } @Override - public Content getFieldDetails(Content fieldDetailsTreeHeader, Content fieldDetailsTree) { + public Content getFieldDetails(Content memberDetailsHeaderContent, Content memberContent) { return writer.getDetailsListItem( HtmlTree.SECTION(HtmlStyle.fieldDetails) .setId(HtmlIds.FIELD_DETAIL) - .add(fieldDetailsTreeHeader) - .add(fieldDetailsTree)); + .add(memberDetailsHeaderContent) + .add(memberContent)); } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.fieldSummaryLabel); - memberTree.add(label); + content.add(label); } @Override @@ -159,7 +159,7 @@ public class FieldWriterImpl extends AbstractMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { Content classLink = writer.getPreQualifiedClassLink( HtmlLinkInfo.Kind.MEMBER, typeElement); Content label; @@ -172,32 +172,32 @@ public class FieldWriterImpl extends AbstractMemberWriter ? resources.getText("doclet.Fields_Inherited_From_Class") : resources.getText("doclet.Fields_Inherited_From_Interface")); } - HtmlTree labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, + var labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label); labelHeading.setId(htmlIds.forInheritedFields(typeElement)); labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); - inheritedTree.add(labelHeading); + content.add(labelHeading); } @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member, - Content tdSummary) { + Content content) { Content memberLink = writer.getDocLink(context, typeElement , member, name(member), HtmlStyle.memberNameLink); - Content code = HtmlTree.CODE(memberLink); - tdSummary.add(code); + var code = HtmlTree.CODE(memberLink); + content.add(code); } @Override - protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { - linksTree.add( + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content target) { + target.add( writer.getDocLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member, name(member))); } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { - addModifierAndType(member, utils.asInstantiatedFieldType(typeElement, (VariableElement)member), tdSummaryType); + protected void addSummaryType(Element member, Content content) { + addModifiersAndType(member, utils.asInstantiatedFieldType(typeElement, (VariableElement)member), content); } @Override @@ -207,7 +207,7 @@ public class FieldWriterImpl extends AbstractMemberWriter } @Override - public Content getMemberTreeHeader(){ - return writer.getMemberTreeHeader(); + public Content getMemberHeader(){ + return writer.getMemberHeader(); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java index 11ed54c2d864f4eb9c6873b3533ea921a0194238..9522a71f6a8b33b2739687cb413add4a01ed3fb4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java @@ -117,8 +117,8 @@ public class HelpWriter extends HtmlDocletWriter { } /** - * Adds the help file contents from the resource file to the content tree. While adding the - * help file contents it also keeps track of user options. + * Adds the help file contents from the resource file to the content. + * While adding the help file contents it also keeps track of user options. * * The general organization is: *

      @@ -127,10 +127,10 @@ public class HelpWriter extends HtmlDocletWriter { *
    • Page-specific help *
    */ - protected void addHelpFileContents(Content contentTree) { - HtmlTree mainTOC = HtmlTree.UL(HtmlStyle.helpTOC); + protected void addHelpFileContents(Content content) { + var mainTOC = HtmlTree.UL(HtmlStyle.helpTOC); - contentTree.add(HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, + content.add(HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, getContent("doclet.help.main_heading"))) .add(mainTOC) .add(new HtmlTree(TagName.HR)) @@ -168,7 +168,7 @@ public class HelpWriter extends HtmlDocletWriter { Content content = new ContentBuilder(); Content navHeading = contents.getContent("doclet.help.navigation.head"); - HtmlTree navSection = HtmlTree.DIV(HtmlStyle.subTitle) + var navSection = HtmlTree.DIV(HtmlStyle.subTitle) .add(HtmlTree.HEADING(Headings.CONTENT_HEADING, navHeading).setId(HtmlIds.HELP_NAVIGATION)) .add(contents.getContent("doclet.help.navigation.intro", overviewLink)); if (options.createIndex()) { @@ -183,24 +183,24 @@ public class HelpWriter extends HtmlDocletWriter { } content.add(navSection); - HtmlTree subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); + var subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); HtmlTree section; // Search if (options.createIndex()) { section = newHelpSection(getContent("doclet.help.search.head"), subTOC, HtmlIds.HELP_SEARCH); - Content searchIntro = HtmlTree.P(getContent("doclet.help.search.intro")); - Content searchExamples = HtmlTree.UL(HtmlStyle.helpSectionList); + var searchIntro = HtmlTree.P(getContent("doclet.help.search.intro")); + var searchExamples = HtmlTree.UL(HtmlStyle.helpSectionList); for (String[] example : SEARCH_EXAMPLES) { searchExamples.add(HtmlTree.LI( getContent("doclet.help.search.example", HtmlTree.CODE(Text.of(example[0])), example[1]))); } - Content searchSpecLink = HtmlTree.A( + var searchSpecLink = HtmlTree.A( resources.getText("doclet.help.search.spec.url", configuration.getDocletVersion().feature()), getContent("doclet.help.search.spec.title")); - Content searchRefer = HtmlTree.P(getContent("doclet.help.search.refer", searchSpecLink)); + var searchRefer = HtmlTree.P(getContent("doclet.help.search.refer", searchSpecLink)); section.add(searchIntro) .add(searchExamples) .add(searchRefer); @@ -234,11 +234,11 @@ public class HelpWriter extends HtmlDocletWriter { */ private Content getPageKindSection(HtmlTree mainTOC) { Content pageKindsHeading = contents.getContent("doclet.help.page_kinds.head"); - HtmlTree pageKindsSection = HtmlTree.DIV(HtmlStyle.subTitle) + var pageKindsSection = HtmlTree.DIV(HtmlStyle.subTitle) .add(HtmlTree.HEADING(Headings.CONTENT_HEADING, pageKindsHeading).setId(HtmlIds.HELP_PAGES)) .add(contents.getContent("doclet.help.page_kinds.intro")); - HtmlTree subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); + var subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); HtmlTree section; @@ -256,7 +256,7 @@ public class HelpWriter extends HtmlDocletWriter { if (configuration.showModules) { section = newHelpSection(contents.moduleLabel, PageMode.MODULE, subTOC); Content moduleIntro = getContent("doclet.help.module.intro"); - Content modulePara = HtmlTree.P(moduleIntro); + var modulePara = HtmlTree.P(moduleIntro); section.add(modulePara) .add(newHelpSectionList( contents.packagesLabel, @@ -451,7 +451,7 @@ public class HelpWriter extends HtmlDocletWriter { } private HtmlTree newHelpSectionList(Content first, Content... rest) { - HtmlTree list = HtmlTree.UL(HtmlStyle.helpSectionList, HtmlTree.LI(first)); + var list = HtmlTree.UL(HtmlStyle.helpSectionList, HtmlTree.LI(first)); List.of(rest).forEach(i -> list.add(HtmlTree.LI(i))); return list; } 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 ac6d395cb25b761355ab0a61310acc131e95df29..30a629288ef5c69b49368081e6feef52fa30ea1f 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 @@ -26,7 +26,6 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; @@ -292,7 +291,7 @@ public class HtmlDocletWriter { * Add method information. * * @param method the method to be documented - * @param dl the content tree to which the method information will be added + * @param dl the content to which the method information will be added */ private void addMethodInfo(ExecutableElement method, Content dl) { TypeElement enclosing = utils.getEnclosingTypeElement(method); @@ -319,19 +318,19 @@ public class HtmlDocletWriter { * Adds the tags information. * * @param e the Element for which the tags will be generated - * @param htmlTree the documentation tree to which the tags will be added + * @param content the content to which the tags will be added */ - protected void addTagsInfo(Element e, Content htmlTree) { + protected void addTagsInfo(Element e, Content content) { if (options.noComment()) { return; } - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); - if (utils.isExecutableElement(e) && !utils.isConstructor(e)) { + var dl = HtmlTree.DL(HtmlStyle.notes); + if (utils.isMethod(e)) { addMethodInfo((ExecutableElement)e, dl); } Content output = getBlockTagOutput(e); dl.add(output); - htmlTree.add(dl); + content.add(dl); } /** @@ -390,7 +389,7 @@ public class HtmlDocletWriter { /** * Returns a TagletWriter that knows how to write HTML. * - * @param context the enclosing context for the trees + * @param context the enclosing context * @return a TagletWriter */ public TagletWriter getTagletWriterInstance(TagletWriterImpl.Context context) { @@ -411,7 +410,7 @@ public class HtmlDocletWriter { String description, Content body) throws DocFileIOException { - printHtmlDocument(metakeywords, description, new ContentBuilder(), Collections.emptyList(), body); + printHtmlDocument(metakeywords, description, new ContentBuilder(), List.of(), body); } /** @@ -485,7 +484,7 @@ public class HtmlDocletWriter { /** * Returns a {@code
    } element, containing the user "top" text, if any, - * amd the main navigation bar. + * and the main navigation bar. * * @param pageMode the pageMode used to configure the navigation bar * @@ -497,7 +496,7 @@ public class HtmlDocletWriter { /** * Returns a {@code
    } element, containing the user "top" text, if any, - * amd the main navigation bar. + * and the main navigation bar. * * @param pageMode the page mode used to configure the navigation bar * @param element the element used to configure the navigation bar @@ -542,24 +541,24 @@ public class HtmlDocletWriter { } /** - * Get the overview tree link for the main tree. + * {@return an "overview tree" link for a navigation bar} * * @param label the label for the link - * @return a content tree for the link */ - protected Content getNavLinkMainTree(String label) { - Content mainTreeContent = links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), + protected Content getNavLinkToOverviewTree(String label) { + Content link = links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), Text.of(label)); - return HtmlTree.LI(mainTreeContent); + return HtmlTree.LI(link); } /** - * Returns a content object containing the package name. A localized content object is - * returned for an unnamed package. Use {@link Utils#getPackageName(PackageElement)} to - * get a static string for the unnamed package instead. + * {@return a package name} * - * @param packageElement the package to check - * @return package name content + * A localized name is returned for an unnamed package. + * Use {@link Utils#getPackageName(PackageElement)} to get a static string + * for the unnamed package instead. + * + * @param packageElement the package to get the name for */ public Content getLocalizedPackageName(PackageElement packageElement) { return packageElement == null || packageElement.isUnnamed() @@ -601,11 +600,10 @@ public class HtmlDocletWriter { } /** - * Return the link to the given package. + * {@return the link to the given package} * * @param packageElement the package to link to. * @param label the label for the link. - * @return a content tree for the package link. */ public Content getPackageLink(PackageElement packageElement, Content label) { boolean included = packageElement != null && utils.isIncluded(packageElement); @@ -650,11 +648,10 @@ public class HtmlDocletWriter { } /** - * Get Module link. + * {@return a link to module} * * @param mdle the module being documented * @param label tag for the link - * @return a content for the module link */ public Content getModuleLink(ModuleElement mdle, Content label) { Set flags = mdle != null ? utils.elementFlags(mdle) @@ -682,13 +679,13 @@ public class HtmlDocletWriter { } /** - * Add the link to the content tree. + * Add the link to the content. * * @param element program element for which the link will be added * @param label label for the link - * @param htmltree the content tree to which the link will be added + * @param target the content to which the link will be added */ - public void addSrcLink(Element element, Content label, Content htmltree) { + public void addSrcLink(Element element, Content label, Content target) { if (element == null) { return; } @@ -703,9 +700,9 @@ public class HtmlDocletWriter { .resolve(docPaths.forClass(te)); Content content = links.createLink(href .fragment(SourceToHTMLConverter.getAnchorName(utils, element).name()), label, ""); - htmltree.add(content); + target.add(content); } else { - htmltree.add(label); + target.add(label); } } @@ -783,11 +780,10 @@ public class HtmlDocletWriter { } /** - * Get the class link. + * {@return a link to the given class} * * @param context the id of the context where the link will be added - * @param element to link to - * @return a content tree for the link + * @param element the class to link to */ public Content getQualifiedClassLink(HtmlLinkInfo.Kind context, Element element) { HtmlLinkInfo htmlLinkInfo = new HtmlLinkInfo(configuration, context, (TypeElement)element); @@ -795,14 +791,14 @@ public class HtmlDocletWriter { } /** - * Add the class link. + * Adds a link to the given class. * * @param context the id of the context where the link will be added - * @param typeElement to link to - * @param contentTree the content tree to which the link will be added + * @param typeElement the class to link to + * @param target the content to which the link will be added */ - public void addPreQualifiedClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content contentTree) { - addPreQualifiedClassLink(context, typeElement, null, contentTree); + public void addPreQualifiedClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content target) { + addPreQualifiedClassLink(context, typeElement, null, target); } /** @@ -832,19 +828,19 @@ public class HtmlDocletWriter { * @param context the id of the context where the link will be added * @param typeElement the class to link to * @param style optional style for the link - * @param contentTree the content tree to which the link with be added + * @param target the content to which the link with be added */ public void addPreQualifiedClassLink(HtmlLinkInfo.Kind context, - TypeElement typeElement, HtmlStyle style, Content contentTree) { + TypeElement typeElement, HtmlStyle style, Content target) { PackageElement pkg = utils.containingPackage(typeElement); if(pkg != null && ! configuration.shouldExcludeQualifier(pkg.getSimpleName().toString())) { - contentTree.add(getEnclosingPackageName(typeElement)); + target.add(getEnclosingPackageName(typeElement)); } HtmlLinkInfo linkinfo = new HtmlLinkInfo(configuration, context, typeElement) .label(utils.getSimpleName(typeElement)) .style(style); Content link = getLink(linkinfo); - contentTree.add(link); + target.add(link); } /** @@ -874,19 +870,18 @@ public class HtmlDocletWriter { * * @param context the id of the context where the link will be added * @param typeElement the class to link to - * @param contentTree the content tree to which the link with be added + * @param content the content to which the link with be added */ - public void addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content contentTree) { - addPreQualifiedClassLink(context, typeElement, HtmlStyle.typeNameLink, contentTree); + public void addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content content) { + addPreQualifiedClassLink(context, typeElement, HtmlStyle.typeNameLink, content); } /** - * Get the link for the given member. + * {@return a link to the given member} * * @param context the id of the context where the link will be added * @param element the member being linked to * @param label the label for the link - * @return a content tree for the element link */ public Content getDocLink(HtmlLinkInfo.Kind context, Element element, CharSequence label) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, @@ -1284,21 +1279,21 @@ public class HtmlDocletWriter { * * @param element the Element for which the inline comment will be added * @param tag the inline tag to be added - * @param htmltree the content tree to which the comment will be added + * @param target the content to which the comment will be added */ - public void addInlineComment(Element element, DocTree tag, Content htmltree) { + public void addInlineComment(Element element, DocTree tag, Content target) { CommentHelper ch = utils.getCommentHelper(element); List description = ch.getDescription(tag); - addCommentTags(element, description, false, false, false, htmltree); + addCommentTags(element, description, false, false, false, target); } /** - * Get the deprecated phrase as content. + * {@return a phrase describing the type of deprecation} * * @param e the Element for which the inline deprecated comment will be added - * @return a content tree for the deprecated phrase. */ public Content getDeprecatedPhrase(Element e) { + // TODO e should be checked to being deprecated return (utils.isDeprecatedForRemoval(e)) ? contents.deprecatedForRemovalPhrase : contents.deprecatedPhrase; @@ -1309,21 +1304,21 @@ public class HtmlDocletWriter { * * @param e the Element for which the inline deprecated comment will be added * @param tag the inline tag to be added - * @param htmltree the content tree to which the comment will be added + * @param target the content to which the comment will be added */ - public void addInlineDeprecatedComment(Element e, DeprecatedTree tag, Content htmltree) { + public void addInlineDeprecatedComment(Element e, DeprecatedTree tag, Content target) { CommentHelper ch = utils.getCommentHelper(e); - addCommentTags(e, ch.getBody(tag), true, false, false, htmltree); + addCommentTags(e, ch.getBody(tag), true, false, false, target); } /** * Adds the summary content. * * @param element the Element for which the summary will be generated - * @param htmltree the documentation tree to which the summary will be added + * @param target the content to which the summary will be added */ - public void addSummaryComment(Element element, Content htmltree) { - addSummaryComment(element, utils.getFirstSentenceTrees(element), htmltree); + public void addSummaryComment(Element element, Content target) { + addSummaryComment(element, utils.getFirstSentenceTrees(element), target); } /** @@ -1331,10 +1326,10 @@ public class HtmlDocletWriter { * * @param element the Element for which the summary will be generated * @param firstSentenceTags the first sentence tags for the doc - * @param htmltree the documentation tree to which the summary will be added + * @param target the content to which the summary will be added */ - public void addPreviewComment(Element element, List firstSentenceTags, Content htmltree) { - addCommentTags(element, firstSentenceTags, false, true, true, htmltree); + public void addPreviewComment(Element element, List firstSentenceTags, Content target) { + addCommentTags(element, firstSentenceTags, false, true, true, target); } /** @@ -1342,26 +1337,26 @@ public class HtmlDocletWriter { * * @param element the Element for which the summary will be generated * @param firstSentenceTags the first sentence tags for the doc - * @param htmltree the documentation tree to which the summary will be added + * @param target the content to which the summary will be added */ - public void addSummaryComment(Element element, List firstSentenceTags, Content htmltree) { - addCommentTags(element, firstSentenceTags, false, true, true, htmltree); + public void addSummaryComment(Element element, List firstSentenceTags, Content target) { + addCommentTags(element, firstSentenceTags, false, true, true, target); } - public void addSummaryDeprecatedComment(Element element, DeprecatedTree tag, Content htmltree) { + public void addSummaryDeprecatedComment(Element element, DeprecatedTree tag, Content target) { CommentHelper ch = utils.getCommentHelper(element); List body = ch.getBody(tag); - addCommentTags(element, ch.getFirstSentenceTrees(body), true, true, true, htmltree); + addCommentTags(element, ch.getFirstSentenceTrees(body), true, true, true, target); } /** * Adds the full-body content of the given element. * * @param element the element for which the content will be added - * @param htmltree the documentation tree to which the content will be added + * @param target the content to which the content will be added */ - public void addInlineComment(Element element, Content htmltree) { - addCommentTags(element, utils.getFullBody(element), false, false, false, htmltree); + public void addInlineComment(Element element, Content target) { + addCommentTags(element, utils.getFullBody(element), false, false, false, target); } /** @@ -1372,10 +1367,10 @@ public class HtmlDocletWriter { * @param depr true if it is deprecated * @param first true if the first sentence tags should be added * @param inSummary true if the comment tags are added into the summary section - * @param htmltree the documentation tree to which the comment tags will be added + * @param target the content to which the comment tags will be added */ private void addCommentTags(Element element, List tags, boolean depr, - boolean first, boolean inSummary, Content htmltree) { + boolean first, boolean inSummary, Content target) { if (options.noComment()) { return; } @@ -1383,13 +1378,13 @@ public class HtmlDocletWriter { Content result = commentTagsToContent(null, element, tags, first, inSummary); if (depr) { div = HtmlTree.DIV(HtmlStyle.deprecationComment, result); - htmltree.add(div); + target.add(div); } else { div = HtmlTree.DIV(HtmlStyle.block, result); - htmltree.add(div); + target.add(div); } if (tags.isEmpty()) { - htmltree.add(Entity.NO_BREAK_SPACE); + target.add(Entity.NO_BREAK_SPACE); } } @@ -1907,35 +1902,33 @@ public class HtmlDocletWriter { } /** - * Return a content tree containing the annotation types for the given element. + * {@return the annotation types info for the given element} * * @param element an Element * @param lineBreak if true add new line between each member value - * @return the documentation tree containing the annotation info */ Content getAnnotationInfo(Element element, boolean lineBreak) { return getAnnotationInfo(element.getAnnotationMirrors(), lineBreak); } /** - * Return a content tree containing the annotation types for the given element. + * {@return the description for the given annotations} * * @param descList a list of annotation mirrors * @param lineBreak if true add new line between each member value - * @return the documentation tree containing the annotation info */ Content getAnnotationInfo(List descList, boolean lineBreak) { List annotations = getAnnotations(descList, lineBreak); String sep = ""; - ContentBuilder builder = new ContentBuilder(); + ContentBuilder result = new ContentBuilder(); for (Content annotation: annotations) { - builder.add(sep); - builder.add(annotation); + result.add(sep); + result.add(annotation); if (!lineBreak) { sep = " "; } } - return builder; + return result; } /** @@ -2249,19 +2242,19 @@ public class HtmlDocletWriter { } /** - * Returns an HtmlTree for the BODY tag. + * Returns an HtmlTree for the BODY element. * * @param title title for the window * @return an HtmlTree for the BODY tag */ public HtmlTree getBody(String title) { - HtmlTree body = new HtmlTree(TagName.BODY).setStyle(getBodyStyle()); + var body = new HtmlTree(TagName.BODY).setStyle(getBodyStyle()); this.winTitle = title; // Don't print windowtitle script for overview-frame, allclasses-frame // and package-frame body.add(mainBodyScript.asContent()); - Content noScript = HtmlTree.NOSCRIPT(HtmlTree.DIV(contents.noScriptMessage)); + var noScript = HtmlTree.NOSCRIPT(HtmlTree.DIV(contents.noScriptMessage)); body.add(noScript); return body; } @@ -2328,7 +2321,7 @@ public class HtmlDocletWriter { public void addPreviewSummary(Element forWhat, Content target) { if (utils.isPreviewAPI(forWhat)) { - Content div = HtmlTree.DIV(HtmlStyle.block); + var div = HtmlTree.DIV(HtmlStyle.block); div.add(HtmlTree.SPAN(HtmlStyle.previewLabel, contents.previewPhrase)); target.add(div); } @@ -2337,7 +2330,7 @@ public class HtmlDocletWriter { public void addPreviewInfo(Element forWhat, Content target) { if (utils.isPreviewAPI(forWhat)) { //in Java platform: - HtmlTree previewDiv = HtmlTree.DIV(HtmlStyle.previewBlock); + var previewDiv = HtmlTree.DIV(HtmlStyle.previewBlock); previewDiv.setId(htmlIds.forPreviewSection(forWhat)); String name = (switch (forWhat.getKind()) { case PACKAGE, MODULE -> @@ -2346,7 +2339,7 @@ public class HtmlDocletWriter { ((TypeElement) forWhat.getEnclosingElement()).getSimpleName(); default -> forWhat.getSimpleName(); }).toString(); - Content nameCode = HtmlTree.CODE(Text.of(name)); + var nameCode = HtmlTree.CODE(Text.of(name)); boolean isReflectivePreview = utils.isReflectivePreviewAPI(forWhat); String leadingNoteKey = !isReflectivePreview ? "doclet.PreviewPlatformLeadingNote" @@ -2367,13 +2360,13 @@ public class HtmlDocletWriter { List previewNotes = getPreviewNotes((TypeElement) forWhat); if (!previewNotes.isEmpty()) { Name name = forWhat.getSimpleName(); - Content nameCode = HtmlTree.CODE(Text.of(name)); - HtmlTree previewDiv = HtmlTree.DIV(HtmlStyle.previewBlock); + var nameCode = HtmlTree.CODE(Text.of(name)); + var previewDiv = HtmlTree.DIV(HtmlStyle.previewBlock); previewDiv.setId(htmlIds.forPreviewSection(forWhat)); Content leadingNote = contents.getContent("doclet.PreviewLeadingNote", nameCode); previewDiv.add(HtmlTree.SPAN(HtmlStyle.previewLabel, leadingNote)); - HtmlTree ul = HtmlTree.UL(HtmlStyle.previewComment); + var ul = HtmlTree.UL(HtmlStyle.previewComment); for (Content note : previewNotes) { ul.add(HtmlTree.LI(note)); } 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 3956987baa9f8beeaaba1893aa4ae2554b6a189c..9c3b7ff0ef26dcc2da61074b41399db9c4e61faa 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 @@ -258,10 +258,10 @@ public class HtmlLinkFactory extends LinkFactory { if (isTypeLink) { return resources.getText("doclet.Href_Type_Param_Title", utils.getSimpleName(typeElement)); - } else if (utils.isInterface(typeElement)){ + } else if (utils.isPlainInterface(typeElement)){ return resources.getText("doclet.Href_Interface_Title", m_writer.getLocalizedPackageName(utils.containingPackage(typeElement))); - } else if (utils.isAnnotationType(typeElement)) { + } else if (utils.isAnnotationInterface(typeElement)) { return resources.getText("doclet.Href_Annotation_Title", m_writer.getLocalizedPackageName(utils.containingPackage(typeElement))); } else if (utils.isEnum(typeElement)) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java index 7278ac8e3155a030914e5c3e29a23a79f92ea423..15960efb815075647abed0e64961c3a87acc9771 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.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 @@ -64,86 +64,67 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl return utils.serializableFields(te); } - /** - * Return the header for serializable fields section. - * - * @return a content tree for the header - */ @Override public Content getSerializableFieldsHeader() { return HtmlTree.UL(HtmlStyle.blockList); } - /** - * Return the header for serializable fields content section. - * - * @param isLastContent true if the content being documented is the last content. - * @return a content tree for the header - */ @Override public Content getFieldsContentHeader(boolean isLastContent) { return new HtmlTree(TagName.LI).setStyle(HtmlStyle.blockList); } - /** - * Add serializable fields. - * - * @param heading the heading for the section - * @param serializableFieldsTree the tree to be added to the serializable fields - * content tree - * @return a content tree for the serializable fields content - */ @Override - public Content getSerializableFields(String heading, Content serializableFieldsTree) { - HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail); - if (serializableFieldsTree.isValid()) { + public Content getSerializableFields(String heading, Content source) { + var section = HtmlTree.SECTION(HtmlStyle.detail); + if (source.isValid()) { Content headingContent = Text.of(heading); - Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); + var serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); section.add(serialHeading); - section.add(serializableFieldsTree); + section.add(source); } return HtmlTree.LI(section); } @Override - public void addMemberHeader(TypeMirror fieldType, String fieldName, Content contentTree) { + public void addMemberHeader(TypeMirror fieldType, String fieldName, Content content) { Content nameContent = Text.of(fieldName); - Content heading = HtmlTree.HEADING(Headings.SerializedForm.MEMBER_HEADING, nameContent); - contentTree.add(heading); - Content pre = new HtmlTree(TagName.PRE); + var heading = HtmlTree.HEADING(Headings.SerializedForm.MEMBER_HEADING, nameContent); + content.add(heading); + var pre = new HtmlTree(TagName.PRE); Content fieldContent = writer.getLink(new HtmlLinkInfo( configuration, HtmlLinkInfo.Kind.SERIAL_MEMBER, fieldType)); pre.add(fieldContent); pre.add(" "); pre.add(fieldName); - contentTree.add(pre); + content.add(pre); } /** * Add the deprecated information for this member. * * @param field the field to document. - * @param contentTree the tree to which the deprecated info will be added + * @param content the content to which the deprecated info will be added */ @Override - public void addMemberDeprecatedInfo(VariableElement field, Content contentTree) { - addDeprecatedInfo(field, contentTree); + public void addMemberDeprecatedInfo(VariableElement field, Content content) { + addDeprecatedInfo(field, content); } /** * Add the description text for this member. * * @param field the field to document. - * @param contentTree the tree to which the deprecated info will be added + * @param content the content to which the deprecated info will be added */ @Override - public void addMemberDescription(VariableElement field, Content contentTree) { + public void addMemberDescription(VariableElement field, Content content) { if (!utils.getFullBody(field).isEmpty()) { - writer.addInlineComment(field, contentTree); + writer.addInlineComment(field, content); } List tags = utils.getSerialTrees(field); if (!tags.isEmpty() && !tags.get(0).getDescription().isEmpty()) { - writer.addInlineComment(field, tags.get(0), contentTree); + writer.addInlineComment(field, tags.get(0), content); } } @@ -151,16 +132,16 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl * Add the description text for this member represented by the tag. * * @param serialFieldTag the field to document (represented by tag) - * @param contentTree the tree to which the deprecated info will be added + * @param content the content to which the deprecated info will be added */ @Override - public void addMemberDescription(VariableElement field, DocTree serialFieldTag, Content contentTree) { + public void addMemberDescription(VariableElement field, DocTree serialFieldTag, Content content) { CommentHelper ch = utils.getCommentHelper(field); List description = ch.getDescription(serialFieldTag); if (!description.isEmpty()) { Content serialFieldContent = new RawHtml(ch.getText(description)); - Content div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent); - contentTree.add(div); + var div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent); + content.add(div); } } @@ -168,15 +149,15 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl * Add the tag information for this member. * * @param field the field to document. - * @param contentTree the tree to which the member tags info will be added + * @param content the content to which the member tags info will be added */ @Override - public void addMemberTags(VariableElement field, Content contentTree) { + public void addMemberTags(VariableElement field, Content content) { Content tagContent = writer.getBlockTagOutput(field); if (!tagContent.isEmpty()) { - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(tagContent); - contentTree.add(dl); + content.add(dl); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java index 8b2bed47a00593cba96ab8b275e7a7b9ae1b13e8..daf11d7f005f469c086ff1d7cb65145f8a554560 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java @@ -53,22 +53,11 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements super(writer, typeElement); } - /** - * Return the header for serializable methods section. - * - * @return a content tree for the header - */ @Override public Content getSerializableMethodsHeader() { return HtmlTree.UL(HtmlStyle.blockList); } - /** - * Return the header for serializable methods content section. - * - * @param isLastContent true if the content being documented is the last content. - * @return a content tree for the header - */ @Override public Content getMethodsContentHeader(boolean isLastContent) { return new HtmlTree(TagName.LI); @@ -78,16 +67,16 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements * Add serializable methods. * * @param heading the heading for the section - * @param serializableMethodContent the tree to be added to the serializable methods - * content tree - * @return a content tree for the serializable methods content + * @param source the content to be added to the serializable methods + * content + * @return a content for the serializable methods content */ @Override - public Content getSerializableMethods(String heading, Content serializableMethodContent) { + public Content getSerializableMethods(String heading, Content source) { Content headingContent = Text.of(heading); - Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); - Content section = HtmlTree.SECTION(HtmlStyle.detail, serialHeading); - section.add(serializableMethodContent); + var serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); + var section = HtmlTree.SECTION(HtmlStyle.detail, serialHeading); + section.add(source); return HtmlTree.LI(section); } @@ -106,51 +95,51 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements * Add the member header. * * @param member the method document to be listed - * @param methodsContentTree the content tree to which the member header will be added + * @param methodsContent the content to which the member header will be added */ @Override - public void addMemberHeader(ExecutableElement member, Content methodsContentTree) { + public void addMemberHeader(ExecutableElement member, Content methodsContent) { Content memberContent = Text.of(name(member)); - Content heading = HtmlTree.HEADING(Headings.SerializedForm.MEMBER_HEADING, memberContent); - methodsContentTree.add(heading); - methodsContentTree.add(getSignature(member)); + var heading = HtmlTree.HEADING(Headings.SerializedForm.MEMBER_HEADING, memberContent); + methodsContent.add(heading); + methodsContent.add(getSignature(member)); } /** * Add the deprecated information for this member. * * @param member the method to document. - * @param methodsContentTree the tree to which the deprecated info will be added + * @param methodsContent the content to which the deprecated info will be added */ @Override - public void addDeprecatedMemberInfo(ExecutableElement member, Content methodsContentTree) { - addDeprecatedInfo(member, methodsContentTree); + public void addDeprecatedMemberInfo(ExecutableElement member, Content methodsContent) { + addDeprecatedInfo(member, methodsContent); } /** * Add the description text for this member. * * @param member the method to document. - * @param methodsContentTree the tree to which the deprecated info will be added + * @param methodsContent the content to which the deprecated info will be added */ @Override - public void addMemberDescription(ExecutableElement member, Content methodsContentTree) { - addComment(member, methodsContentTree); + public void addMemberDescription(ExecutableElement member, Content methodsContent) { + addComment(member, methodsContent); } /** * Add the tag information for this member. * * @param member the method to document. - * @param methodsContentTree the tree to which the member tags info will be added + * @param methodsContent the content to which the member tags info will be added */ @Override - public void addMemberTags(ExecutableElement member, Content methodsContentTree) { + public void addMemberTags(ExecutableElement member, Content methodsContent) { TagletManager tagletManager = configuration.tagletManager; Content tagContent = writer.getBlockTagOutput(member, tagletManager.getSerializedFormTaglets()); - HtmlTree dl = HtmlTree.DL(HtmlStyle.notes); + var dl = HtmlTree.DL(HtmlStyle.notes); dl.add(tagContent); - methodsContentTree.add(dl); + methodsContent.add(dl); if (name(member).equals("writeExternal") && utils.getSerialDataTrees(member).isEmpty()) { serialWarning(member, "doclet.MissingSerialDataTag", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java index 299e565a65782735981e105330e9a7a8ee329675..976b78ad23b86144584e56ecc7c834ed03986172 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java @@ -25,7 +25,7 @@ package jdk.javadoc.internal.doclets.formats.html; -import java.util.Collections; +import java.util.List; import jdk.javadoc.internal.doclets.formats.html.markup.Head; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; @@ -78,7 +78,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter { .setTimestamp(!options.noTimestamp()) .setDescription("index redirect") .setGenerator(getGenerator(getClass())) - .setStylesheets(configuration.getMainStylesheet(), Collections.emptyList()) // avoid reference to default stylesheet + .setStylesheets(configuration.getMainStylesheet(), List.of()) // avoid reference to default stylesheet .addDefaultScript(false); String title = (options.windowTitle().length() > 0) @@ -93,7 +93,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter { Script script = new Script("window.location.replace(") .appendStringLiteral(targetPath, '\'') .append(")"); - HtmlTree metaRefresh = new HtmlTree(TagName.META) + var metaRefresh = new HtmlTree(TagName.META) .put(HtmlAttr.HTTP_EQUIV, "Refresh") .put(HtmlAttr.CONTENT, "0;" + targetPath); head.addContent(script.asContent(), HtmlTree.NOSCRIPT(metaRefresh)); @@ -104,8 +104,8 @@ public class IndexRedirectWriter extends HtmlDocletWriter { bodyContent.add(HtmlTree.P(HtmlTree.A(targetPath, Text.of(targetPath)))); - Content body = new HtmlTree(TagName.BODY).setStyle(HtmlStyle.indexRedirectPage); - HtmlTree main = HtmlTree.MAIN(bodyContent); + var body = new HtmlTree(TagName.BODY).setStyle(HtmlStyle.indexRedirectPage); + var main = HtmlTree.MAIN(bodyContent); body.add(main); HtmlDocument htmlDocument = new HtmlDocument( diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java index 9e486b74ab9af8a8021a9ee8a75eccb2ad31d728..a75509be6c4ab0498ed7700d14f2808b1bab6d27 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java @@ -144,31 +144,31 @@ public class IndexWriter extends HtmlDocletWriter { /** * Adds a set of items to the page. * - * @param ch the first character of the names of the items - * @param items the items - * @param contentTree the tree to which to add the items + * @param ch the first character of the names of the items + * @param items the items + * @param content the content to which to add the items */ - protected void addContents(char ch, SortedSet items, Content contentTree) { - addHeading(ch, contentTree); + protected void addContents(char ch, SortedSet items, Content content) { + addHeading(ch, content); - HtmlTree dl = HtmlTree.DL(HtmlStyle.index); + var dl = HtmlTree.DL(HtmlStyle.index); for (IndexItem item : items) { addDescription(item, dl); } - contentTree.add(dl); + content.add(dl); } /** * Adds a heading containing the first character for a set of items. * - * @param ch the first character of the names of the items - * @param contentTree the tree to which to add the items + * @param ch the first character of the names of the items + * @param content the content to which to add the items */ - protected void addHeading(char ch, Content contentTree) { + protected void addHeading(char ch, Content content) { Content headContent = Text.of(String.valueOf(ch)); - HtmlTree heading = HtmlTree.HEADING(Headings.CONTENT_HEADING, HtmlStyle.title, headContent) + var heading = HtmlTree.HEADING(Headings.CONTENT_HEADING, HtmlStyle.title, headContent) .setId(HtmlIds.forIndexChar(ch)); - contentTree.add(heading); + content.add(heading); } /** @@ -189,9 +189,9 @@ public class IndexWriter extends HtmlDocletWriter { * Add one line summary comment for the item. * * @param item the item to be documented - * @param dlTree the content tree to which the description will be added + * @param target the content to which the description will be added */ - protected void addElementDescription(IndexItem item, Content dlTree) { + protected void addElementDescription(IndexItem item, Content target) { Content dt; Element element = item.getElement(); String label = item.getLabel(); @@ -234,24 +234,24 @@ public class IndexWriter extends HtmlDocletWriter { default: throw new Error(); } - dlTree.add(dt); - Content dd = new HtmlTree(TagName.DD); + target.add(dt); + var dd = new HtmlTree(TagName.DD); if (element.getKind() == ElementKind.MODULE || element.getKind() == ElementKind.PACKAGE) { addSummaryComment(element, dd); } else { addComment(element, dd); } - dlTree.add(dd); + target.add(dd); } /** * Adds information for the given type element. * - * @param te the element - * @param contentTree the content tree to which the class info will be added + * @param te the element + * @param content the content to which the class info will be added */ - protected void addClassInfo(TypeElement te, Content contentTree) { - contentTree.add(contents.getContent("doclet.in", + protected void addClassInfo(TypeElement te, Content content) { + content.add(contents.getContent("doclet.in", utils.getTypeElementKindName(te, false), getPackageLink(utils.containingPackage(te), getLocalizedPackageName(utils.containingPackage(te))) @@ -262,23 +262,23 @@ public class IndexWriter extends HtmlDocletWriter { * Adds a description for an item found in a documentation comment. * * @param item the item - * @param dlTree the list to which to add the description + * @param target the list to which to add the description */ - protected void addTagDescription(IndexItem item, Content dlTree) { + protected void addTagDescription(IndexItem item, Content target) { String itemPath = pathToRoot.isEmpty() ? "" : pathToRoot.getPath() + "/"; itemPath += item.getUrl(); - HtmlTree labelLink = HtmlTree.A(itemPath, Text.of(item.getLabel())); - Content dt = HtmlTree.DT(labelLink.setStyle(HtmlStyle.searchTagLink)); + var labelLink = HtmlTree.A(itemPath, Text.of(item.getLabel())); + var dt = HtmlTree.DT(labelLink.setStyle(HtmlStyle.searchTagLink)); dt.add(" - "); dt.add(contents.getContent("doclet.Search_tag_in", item.getHolder())); - dlTree.add(dt); - Content dd = new HtmlTree(TagName.DD); + target.add(dt); + var dd = new HtmlTree(TagName.DD); if (item.getDescription().isEmpty()) { dd.add(Entity.NO_BREAK_SPACE); } else { dd.add(item.getDescription()); } - dlTree.add(dd); + target.add(dd); } /** @@ -288,39 +288,39 @@ public class IndexWriter extends HtmlDocletWriter { * the start and then print the normal comment. * * @param element the element - * @param contentTree the content tree to which the comment will be added + * @param content the content to which the comment will be added */ - protected void addComment(Element element, Content contentTree) { - Content span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(element)); - HtmlTree div = HtmlTree.DIV(HtmlStyle.deprecationBlock); + protected void addComment(Element element, Content content) { + var span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(element)); + var div = HtmlTree.DIV(HtmlStyle.deprecationBlock); if (utils.isDeprecated(element)) { div.add(span); List tags = utils.getDeprecatedTrees(element); if (!tags.isEmpty()) addInlineDeprecatedComment(element, tags.get(0), div); - contentTree.add(div); + content.add(div); } else { TypeElement encl = utils.getEnclosingTypeElement(element); while (encl != null) { if (utils.isDeprecated(encl)) { div.add(span); - contentTree.add(div); + content.add(div); break; } encl = utils.getEnclosingTypeElement(encl); } - addSummaryComment(element, contentTree); + addSummaryComment(element, content); } } /** * Adds a description for a member element. * - * @param member the element - * @param enclosing the enclosing type element - * @param contentTree the content tree to which the member description will be added + * @param member the element + * @param enclosing the enclosing type element + * @param content the content to which the member description will be added */ - protected void addMemberDesc(Element member, TypeElement enclosing, Content contentTree) { + protected void addMemberDesc(Element member, TypeElement enclosing, Content content) { String kindName = utils.getTypeElementKindName(enclosing, true); String resource = switch (member.getKind()) { case ENUM_CONSTANT -> @@ -330,24 +330,24 @@ public class IndexWriter extends HtmlDocletWriter { case CONSTRUCTOR -> "doclet.Constructor_for"; case METHOD -> - utils.isAnnotationType(enclosing) ? "doclet.Element_in" + utils.isAnnotationInterface(enclosing) ? "doclet.Element_in" : utils.isStatic(member) ? "doclet.Static_method_in" : "doclet.Method_in"; case RECORD_COMPONENT -> "doclet.Record_component_in"; default -> throw new IllegalArgumentException(member.getKind().toString()); }; - contentTree.add(contents.getContent(resource, kindName)).add(" "); + content.add(contents.getContent(resource, kindName)).add(" "); addPreQualifiedClassLink(HtmlLinkInfo.Kind.INDEX, enclosing, - null, contentTree); + null, content); } /** * Add links for all the index files, based on the first character of the names of the items. * * @param allFirstCharacters the list of all first characters to be linked - * @param contentTree the content tree to which the links for indexes will be added + * @param content the content to which the links for indexes will be added */ - protected void addLinksForIndexes(List allFirstCharacters, Content contentTree) { + protected void addLinksForIndexes(List allFirstCharacters, Content content) { ListIterator iter = allFirstCharacters.listIterator(); while (iter.hasNext()) { char ch = iter.next(); @@ -355,11 +355,11 @@ public class IndexWriter extends HtmlDocletWriter { Content link = splitIndex ? links.createLink(DocPaths.indexN(iter.nextIndex()), label) : links.createLink(HtmlIds.forIndexChar(ch), label); - contentTree.add(link); - contentTree.add(Entity.NO_BREAK_SPACE); + content.add(link); + content.add(Entity.NO_BREAK_SPACE); } - contentTree.add(new HtmlTree(TagName.BR)); + content.add(new HtmlTree(TagName.BR)); List pageLinks = Stream.of(IndexItem.Category.values()) .flatMap(c -> mainIndex.getItems(c).stream()) .filter(i -> !(i.isElementItem() || i.isTagItem())) @@ -367,7 +367,7 @@ public class IndexWriter extends HtmlDocletWriter { .map(i -> links.createLink(pathToRoot.resolve(i.getUrl()), contents.getNonBreakString(i.getLabel()))) .toList(); - contentTree.add(contents.join(getVerticalSeparator(), pageLinks)); + content.add(contents.join(getVerticalSeparator(), pageLinks)); } private Content getVerticalSeparator() { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java index 9ba0a2222ea812b5cba6b4a452bbfaad6397b5db..859908078b8d027540082f81f3a780d4297275fa 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.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 @@ -76,11 +76,11 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } @Override - public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_METHOD_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + public Content getMemberSummaryHeader(TypeElement typeElement, Content target) { + target.add(MarkerComments.START_OF_METHOD_SUMMARY); + Content memberContent = new ContentBuilder(); + writer.addSummaryHeader(this, memberContent); + return memberContent; } @Override @@ -90,35 +90,29 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } @Override - public Content getMethodDetailsTreeHeader(Content memberDetailsTree) { - memberDetailsTree.add(MarkerComments.START_OF_METHOD_DETAILS); - Content methodDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getMethodDetailsHeader(Content content) { + content.add(MarkerComments.START_OF_METHOD_DETAILS); + Content methodDetailsContent = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.methodDetailLabel); - methodDetailsTree.add(heading); - return methodDetailsTree; + methodDetailsContent.add(heading); + return methodDetailsContent; } @Override - public Content getMethodDocTreeHeader(ExecutableElement method) { - Content methodDocTree = new ContentBuilder(); - HtmlTree heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getMethodHeader(ExecutableElement method) { + Content content = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(name(method))); HtmlId erasureAnchor; if ((erasureAnchor = htmlIds.forErasure(method)) != null) { heading.setId(erasureAnchor); } - methodDocTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, methodDocTree) + content.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, content) .setId(htmlIds.forMember(method)); } - /** - * Get the signature for the given method. - * - * @param method the method being documented. - * @return a content object for the signature - */ @Override public Content getSignature(ExecutableElement method) { return new Signatures.MemberSignature(method, this) @@ -131,23 +125,23 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } @Override - public void addDeprecated(ExecutableElement method, Content methodDocTree) { - addDeprecatedInfo(method, methodDocTree); + public void addDeprecated(ExecutableElement method, Content methodContent) { + addDeprecatedInfo(method, methodContent); } @Override - public void addPreview(ExecutableElement method, Content methodDocTree) { - addPreviewInfo(method, methodDocTree); + public void addPreview(ExecutableElement method, Content content) { + addPreviewInfo(method, content); } @Override - public void addComments(TypeMirror holderType, ExecutableElement method, Content methodDocTree) { + public void addComments(TypeMirror holderType, ExecutableElement method, Content methodContent) { TypeElement holder = utils.asTypeElement(holderType); if (!utils.getFullBody(method).isEmpty()) { if (holder.equals(typeElement) || !(utils.isPublic(holder) || utils.isLinkable(holder))) { - writer.addInlineComment(method, methodDocTree); + writer.addInlineComment(method, methodContent); } else { if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(method)) { Content link = @@ -156,37 +150,37 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter utils.isIncluded(holder) ? utils.getSimpleName(holder) : utils.getFullyQualifiedName(holder)); - Content codeLink = HtmlTree.CODE(link); - Content descriptionFromTypeLabel = HtmlTree.SPAN(HtmlStyle.descriptionFromTypeLabel, + var codeLink = HtmlTree.CODE(link); + var descriptionFromTypeLabel = HtmlTree.SPAN(HtmlStyle.descriptionFromTypeLabel, utils.isClass(holder) ? contents.descriptionFromClassLabel : contents.descriptionFromInterfaceLabel); descriptionFromTypeLabel.add(Entity.NO_BREAK_SPACE); descriptionFromTypeLabel.add(codeLink); - methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descriptionFromTypeLabel)); + methodContent.add(HtmlTree.DIV(HtmlStyle.block, descriptionFromTypeLabel)); } - writer.addInlineComment(method, methodDocTree); + writer.addInlineComment(method, methodContent); } } } @Override - public void addTags(ExecutableElement method, Content methodDocTree) { - writer.addTagsInfo(method, methodDocTree); + public void addTags(ExecutableElement method, Content methodContent) { + writer.addTagsInfo(method, methodContent); } @Override - public Content getMethodDetails(Content methodDetailsTreeHeader, Content methodDetailsTree) { - Content methodDetails = new ContentBuilder(methodDetailsTreeHeader, methodDetailsTree); - return getMemberTree(HtmlTree.SECTION(HtmlStyle.methodDetails, methodDetails) + public Content getMethodDetails(Content methodDetailsHeader, Content methodDetails) { + Content c = new ContentBuilder(methodDetailsHeader, methodDetails); + return getMember(HtmlTree.SECTION(HtmlStyle.methodDetails, c) .setId(HtmlIds.METHOD_DETAIL)); } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.methodSummary); - memberTree.add(label); + content.add(label); } @Override @@ -206,14 +200,14 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter .addTab(contents.getContent("doclet.Instance_Methods"), e -> !utils.isStatic(e)) .addTab(contents.getContent("doclet.Abstract_Methods"), utils::isAbstract) .addTab(contents.getContent("doclet.Concrete_Methods"), - e -> !utils.isAbstract(e) && !utils.isInterface(e.getEnclosingElement())) + e -> !utils.isAbstract(e) && !utils.isPlainInterface(e.getEnclosingElement())) .addTab(contents.getContent("doclet.Default_Methods"), utils::isDefault) .addTab(contents.getContent("doclet.Deprecated_Methods"), e -> utils.isDeprecated(e) || utils.isDeprecated(typeElement)); } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { Content classLink = writer.getPreQualifiedClassLink( HtmlLinkInfo.Kind.MEMBER, typeElement); Content label; @@ -226,18 +220,18 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter ? resources.getText("doclet.Methods_Inherited_From_Class") : resources.getText("doclet.Methods_Inherited_From_Interface")); } - HtmlTree labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, + var labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label); labelHeading.setId(htmlIds.forInheritedMethods(typeElement)); labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); - inheritedTree.add(labelHeading); + content.add(labelHeading); } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { + protected void addSummaryType(Element member, Content content) { ExecutableElement meth = (ExecutableElement)member; - addModifierAndType(meth, utils.getReturnType(typeElement, meth), tdSummaryType); + addModifiersAndType(meth, utils.getReturnType(typeElement, meth), content); } /** @@ -286,13 +280,13 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter dl.add(HtmlTree.DT(label)); Content overriddenTypeLink = writer.getLink(new HtmlLinkInfo(writer.configuration, context, overriddenType)); - Content codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink); + var codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink); Content methlink = writer.getLink( new HtmlLinkInfo(writer.configuration, HtmlLinkInfo.Kind.MEMBER, holder) .where(writer.htmlIds.forMember(method).name()) .label(method.getSimpleName())); - Content codeMethLink = HtmlTree.CODE(methlink); - Content dd = HtmlTree.DD(codeMethLink); + var codeMethLink = HtmlTree.CODE(methlink); + var dd = HtmlTree.DD(codeMethLink); dd.add(Entity.NO_BREAK_SPACE); dd.add(contents.inClass); dd.add(Entity.NO_BREAK_SPACE); @@ -326,13 +320,13 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac); Content intfaclink = writer.getLink(new HtmlLinkInfo( writer.configuration, HtmlLinkInfo.Kind.METHOD_SPECIFIED_BY, intfac)); - Content codeIntfacLink = HtmlTree.CODE(intfaclink); + var codeIntfacLink = HtmlTree.CODE(intfaclink); dl.add(HtmlTree.DT(contents.specifiedByLabel)); Content methlink = writer.getDocLink( HtmlLinkInfo.Kind.MEMBER, implementedMeth, implementedMeth.getSimpleName()); - Content codeMethLink = HtmlTree.CODE(methlink); - Content dd = HtmlTree.DD(codeMethLink); + var codeMethLink = HtmlTree.CODE(methlink); + var dd = HtmlTree.DD(codeMethLink); dd.add(Entity.NO_BREAK_SPACE); dd.add(contents.inInterface); dd.add(Entity.NO_BREAK_SPACE); @@ -345,7 +339,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter * Get the return type for the given method. * * @param method the method being documented. - * @return content containing the return type + * @return the return type */ protected Content getReturnType(ExecutableElement method) { TypeMirror type = utils.getReturnType(typeElement, method); @@ -356,7 +350,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } @Override - public Content getMemberTreeHeader(){ - return writer.getMemberTreeHeader(); + public Content getMemberHeader(){ + return writer.getMemberHeader(); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java index 934f9e67ff6d71d734b491edb1d69b995de8353c..55bc0f23009a0c6005a71e99d7a1812a4f933ce5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.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 @@ -80,10 +80,10 @@ public class ModuleIndexWriter extends AbstractOverviewIndexWriter { /** * Adds the list of modules. * - * @param main the documentation tree to which the modules list will be added + * @param target the content to which the modules list will be added */ @Override - protected void addIndex(Content main) { + protected void addIndex(Content target) { Map> groupModuleMap = configuration.group.groupModules(modules); @@ -115,7 +115,7 @@ public class ModuleIndexWriter extends AbstractOverviewIndexWriter { } } - main.add(table); + target.add(table); if (table.needsScript()) { mainBodyScript.append(table.getScript()); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index 30803551b2fc66bf6d3825f1b93a0c39515ae68f..6de7880d8f14677bfc921ebfd6103449b317744e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -26,7 +26,6 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -172,25 +171,20 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW computeModulesData(); } - /** - * Get the module header. - * - * @param heading the heading for the section - */ @Override public Content getModuleHeader(String heading) { - HtmlTree bodyTree = getBody(getWindowTitle(mdle.getQualifiedName().toString())); - HtmlTree div = HtmlTree.DIV(HtmlStyle.header); + HtmlTree body = getBody(getWindowTitle(mdle.getQualifiedName().toString())); + var div = HtmlTree.DIV(HtmlStyle.header); Content moduleHead = new ContentBuilder(); moduleHead.add(mdle.isOpen() && (configuration.docEnv.getModuleMode() == ModuleMode.ALL) ? contents.openModuleLabel : contents.moduleLabel); moduleHead.add(" ").add(heading); - Content tHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var tHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, moduleHead); div.add(tHeading); bodyContents.setHeader(getHeader(PageMode.MODULE, mdle)) .addMainContent(div); - return bodyTree; + return body; } @Override @@ -208,30 +202,19 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW )); } - /** - * Get the content header. - */ @Override public Content getContentHeader() { return new ContentBuilder(); } - /** - * Get the summary section header. - */ @Override public Content getSummariesList() { return HtmlTree.UL(HtmlStyle.summaryList); } - /** - * Get the summary tree. - * - * @param summaryContentTree the content tree to be added to the summary tree. - */ @Override - public Content getSummaryTree(Content summaryContentTree) { - return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree); + public Content getSummary(Content source) { + return HtmlTree.SECTION(HtmlStyle.summary, source); } /** @@ -264,11 +247,11 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW }); // Get all packages if module is open or if displaying concealed modules - for (PackageElement pkg : utils.getModulePackageMap().getOrDefault(mdle, Collections.emptySet())) { + for (PackageElement pkg : utils.getModulePackageMap().getOrDefault(mdle, Set.of())) { if (shouldDocument(pkg) && (mdle.isOpen() || moduleMode == ModuleMode.ALL)) { PackageEntry e = new PackageEntry(); if (mdle.isOpen()) { - e.openedTo = Collections.emptySet(); + e.openedTo = Set.of(); } packages.put(pkg, e); } @@ -329,7 +312,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW } SortedSet openPackages = new TreeSet<>(utils.comparators.makePackageComparator()); if (module.isOpen()) { - openPackages.addAll(utils.getModulePackageMap().getOrDefault(module, Collections.emptySet())); + openPackages.addAll(utils.getModulePackageMap().getOrDefault(module, Set.of())); } else { ElementFilter.opensIn(module.getDirectives()).forEach(directive -> { PackageElement pkg = directive.getPackage(); @@ -434,12 +417,12 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW * * @param startMarker the marker comment * @param heading the heading for the section - * @param htmltree the content tree to which the information is added + * @param target the content to which the information is added */ public void addSummaryHeader(Content startMarker, Content heading, - Content htmltree) { - htmltree.add(startMarker); - htmltree.add(HtmlTree.HEADING(Headings.ModuleDeclaration.SUMMARY_HEADING, heading)); + Content target) { + target.add(startMarker); + target.add(HtmlTree.HEADING(Headings.ModuleDeclaration.SUMMARY_HEADING, heading)); } /** @@ -476,7 +459,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW TableHeader requiresTableHeader = new TableHeader(contents.modifierLabel, contents.moduleLabel, contents.descriptionLabel); - HtmlTree section = HtmlTree.SECTION(HtmlStyle.modulesSummary) + var section = HtmlTree.SECTION(HtmlStyle.modulesSummary) .setId(HtmlIds.MODULES); addSummaryHeader(MarkerComments.START_OF_MODULES_SUMMARY, contents.navModules, section); if (display(requires)) { @@ -518,7 +501,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW public void addPackagesSummary(Content summariesList) { if (display(packages) || display(indirectPackages) || display(indirectOpenPackages)) { - HtmlTree section = HtmlTree.SECTION(HtmlStyle.packagesSummary) + var section = HtmlTree.SECTION(HtmlStyle.packagesSummary) .setId(HtmlIds.PACKAGES); addSummaryHeader(MarkerComments.START_OF_PACKAGES_SUMMARY, contents.navPackages, section); if (display(packages)) { @@ -691,7 +674,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW boolean haveProvides = displayServices(provides.keySet(), providesTrees); if (haveProvides || haveUses) { - HtmlTree section = HtmlTree.SECTION(HtmlStyle.servicesSummary) + var section = HtmlTree.SECTION(HtmlStyle.servicesSummary) .setId(HtmlIds.SERVICES); addSummaryHeader(MarkerComments.START_OF_SERVICES_SUMMARY, contents.navServices, section); TableHeader usesProvidesTableHeader = @@ -774,7 +757,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) { desc.add(new HtmlTree(TagName.BR)); desc.add("("); - HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); + var implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); desc.add(implSpan); desc.add(Entity.NO_BREAK_SPACE); String sep = ""; @@ -792,14 +775,14 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW /** * Add the module deprecation information to the documentation tree. * - * @param div the content tree to which the deprecation information will be added + * @param div the content to which the deprecation information will be added */ public void addDeprecationInfo(Content div) { List deprs = utils.getDeprecatedTrees(mdle); if (utils.isDeprecated(mdle)) { CommentHelper ch = utils.getCommentHelper(mdle); - HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); - Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle)); + var deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); + var deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { List commentTags = ch.getDescription(deprs.get(0)); @@ -812,28 +795,28 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW } @Override - public void addModuleDescription(Content moduleContentTree) { - addPreviewInfo(mdle, moduleContentTree); + public void addModuleDescription(Content moduleContent) { + addPreviewInfo(mdle, moduleContent); if (!utils.getFullBody(mdle).isEmpty()) { - HtmlTree tree = HtmlTree.SECTION(HtmlStyle.moduleDescription) + var tree = HtmlTree.SECTION(HtmlStyle.moduleDescription) .setId(HtmlIds.MODULE_DESCRIPTION); addDeprecationInfo(tree); tree.add(MarkerComments.START_OF_MODULE_DESCRIPTION); addInlineComment(mdle, tree); addTagsInfo(mdle, tree); - moduleContentTree.add(tree); + moduleContent.add(tree); } } @Override - public void addModuleSignature(Content moduleContentTree) { - moduleContentTree.add(new HtmlTree(TagName.HR)); - moduleContentTree.add(Signatures.getModuleSignature(mdle, this)); + public void addModuleSignature(Content moduleContent) { + moduleContent.add(new HtmlTree(TagName.HR)); + moduleContent.add(Signatures.getModuleSignature(mdle, this)); } @Override - public void addModuleContent(Content moduleContentTree) { - bodyContents.addMainContent(moduleContentTree); + public void addModuleContent(Content source) { + bodyContents.addMainContent(source); } @Override @@ -842,23 +825,23 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW } @Override - public void printDocument(Content contentTree) throws DocFileIOException { - contentTree.add(bodyContents); + public void printDocument(Content content) throws DocFileIOException { + content.add(bodyContents); printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle), - getDescription("declaration", mdle), getLocalStylesheets(mdle), contentTree); + getDescription("declaration", mdle), getLocalStylesheets(mdle), content); } /** * Add the module package deprecation information to the documentation tree. * - * @param li the content tree to which the deprecation information will be added + * @param li the content to which the deprecation information will be added * @param pkg the PackageDoc that is added */ public void addPackageDeprecationInfo(Content li, PackageElement pkg) { if (utils.isDeprecated(pkg)) { List deprs = utils.getDeprecatedTrees(pkg); - HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); - Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg)); + var deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); + var deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { CommentHelper ch = utils.getCommentHelper(pkg); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java index 3e8e556974a300210e1bc63c8db5101ac9eaf63a..b070e30112eed33eea9e4e134adbb2ec37a48fb0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java @@ -162,154 +162,154 @@ public class Navigation { /** * Adds the links for the main navigation. * - * @param tree the content tree to which the main navigation will added + * @param target the content to which the main navigation will added */ - private void addMainNavLinks(Content tree) { + private void addMainNavLinks(Content target) { switch (documentedPage) { case OVERVIEW: - addActivePageLink(tree, contents.overviewLabel, options.createOverview()); - addModuleLink(tree); - addPackageLink(tree); - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addTreeLink(tree); - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addActivePageLink(target, contents.overviewLabel, options.createOverview()); + addModuleLink(target); + addPackageLink(target); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addTreeLink(target); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case MODULE: - addOverviewLink(tree); - addActivePageLink(tree, contents.moduleLabel, configuration.showModules); - addPackageLink(tree); - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addTreeLink(tree); - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addOverviewLink(target); + addActivePageLink(target, contents.moduleLabel, configuration.showModules); + addPackageLink(target); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addTreeLink(target); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case PACKAGE: - addOverviewLink(tree); - addModuleOfElementLink(tree); - addActivePageLink(tree, contents.packageLabel, true); - addPageLabel(tree, contents.classLabel, true); + addOverviewLink(target); + addModuleOfElementLink(target); + addActivePageLink(target, contents.packageLabel, true); + addPageLabel(target, contents.classLabel, true); if (options.classUse()) { - addContentToTree(tree, links.createLink(DocPaths.PACKAGE_USE, + addItemToList(target, links.createLink(DocPaths.PACKAGE_USE, contents.useLabel, "")); } if (options.createTree()) { - addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, + addItemToList(target, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel, "")); } - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case CLASS: - addOverviewLink(tree); - addModuleOfElementLink(tree); - addPackageSummaryLink(tree); - addActivePageLink(tree, contents.classLabel, true); + addOverviewLink(target); + addModuleOfElementLink(target); + addPackageSummaryLink(target); + addActivePageLink(target, contents.classLabel, true); if (options.classUse()) { - addContentToTree(tree, links.createLink(DocPaths.CLASS_USE.resolve(path.basename()), + addItemToList(target, links.createLink(DocPaths.CLASS_USE.resolve(path.basename()), contents.useLabel)); } if (options.createTree()) { - addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, + addItemToList(target, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel, "")); } - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case USE: - addOverviewLink(tree); - addModuleOfElementLink(tree); + addOverviewLink(target); + addModuleOfElementLink(target); if (element instanceof PackageElement) { - addPackageSummaryLink(tree); - addPageLabel(tree, contents.classLabel, true); + addPackageSummaryLink(target); + addPageLabel(target, contents.classLabel, true); } else { - addPackageOfElementLink(tree); - addContentToTree(tree, navLinkClass); + addPackageOfElementLink(target); + addItemToList(target, navLinkClass); } - addActivePageLink(tree, contents.useLabel, options.classUse()); + addActivePageLink(target, contents.useLabel, options.classUse()); if (element instanceof PackageElement) { - addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel)); + addItemToList(target, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel)); } else { - addContentToTree(tree, configuration.utils.isEnclosingPackageIncluded((TypeElement) element) + addItemToList(target, configuration.utils.isEnclosingPackageIncluded((TypeElement) element) ? links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel) : links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel)); } - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case TREE: - addOverviewLink(tree); + addOverviewLink(target); if (element == null) { - addPageLabel(tree, contents.moduleLabel, configuration.showModules); - addPageLabel(tree, contents.packageLabel, true); + addPageLabel(target, contents.moduleLabel, configuration.showModules); + addPageLabel(target, contents.packageLabel, true); } else { - addModuleOfElementLink(tree); - addPackageSummaryLink(tree); + addModuleOfElementLink(target); + addPackageSummaryLink(target); } - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addActivePageLink(tree, contents.treeLabel, options.createTree()); - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addActivePageLink(target, contents.treeLabel, options.createTree()); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case DEPRECATED: case INDEX: case HELP: case PREVIEW: case NEW: - addOverviewLink(tree); - addModuleLink(tree); - addPackageLink(tree); - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addTreeLink(tree); + addOverviewLink(target); + addModuleLink(target); + addPackageLink(target); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addTreeLink(target); if (documentedPage == PageMode.PREVIEW) { - addActivePageLink(tree, contents.previewLabel, + addActivePageLink(target, contents.previewLabel, configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.PREVIEW)); } else { - addPreviewLink(tree); + addPreviewLink(target); } if (documentedPage == PageMode.NEW) { - addActivePageLink(tree, contents.newLabel, + addActivePageLink(target, contents.newLabel, configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.NEW)); } else { - addNewLink(tree); + addNewLink(target); } if (documentedPage == PageMode.DEPRECATED) { - addActivePageLink(tree, contents.deprecatedLabel, + addActivePageLink(target, contents.deprecatedLabel, configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.DEPRECATED)); } else { - addDeprecatedLink(tree); + addDeprecatedLink(target); } if (documentedPage == PageMode.INDEX) { - addActivePageLink(tree, contents.indexLabel, options.createIndex()); + addActivePageLink(target, contents.indexLabel, options.createIndex()); } else { - addIndexLink(tree); + addIndexLink(target); } if (documentedPage == PageMode.HELP) { - addActivePageLink(tree, contents.helpLabel, !options.noHelp()); + addActivePageLink(target, contents.helpLabel, !options.noHelp()); } else { - addHelpLink(tree); + addHelpLink(target); } break; case ALL_CLASSES: @@ -317,30 +317,30 @@ public class Navigation { case CONSTANT_VALUES: case SERIALIZED_FORM: case SYSTEM_PROPERTIES: - addOverviewLink(tree); - addModuleLink(tree); - addPackageLink(tree); - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addTreeLink(tree); - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addOverviewLink(target); + addModuleLink(target); + addPackageLink(target); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addTreeLink(target); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; case DOC_FILE: - addOverviewLink(tree); - addModuleOfElementLink(tree); - addContentToTree(tree, navLinkPackage); - addPageLabel(tree, contents.classLabel, true); - addPageLabel(tree, contents.useLabel, options.classUse()); - addTreeLink(tree); - addPreviewLink(tree); - addNewLink(tree); - addDeprecatedLink(tree); - addIndexLink(tree); - addHelpLink(tree); + addOverviewLink(target); + addModuleOfElementLink(target); + addItemToList(target, navLinkPackage); + addPageLabel(target, contents.classLabel, true); + addPageLabel(target, contents.useLabel, options.classUse()); + addTreeLink(target); + addPreviewLink(target); + addNewLink(target); + addDeprecatedLink(target); + addIndexLink(target); + addHelpLink(target); break; default: break; @@ -350,10 +350,10 @@ public class Navigation { /** * Adds the summary links to the sub-navigation. * - * @param tree the content tree to which the sub-navigation will added + * @param target the content to which the sub-navigation will be added * @param nested whether to create a flat or nested list */ - private void addSummaryLinks(Content tree, boolean nested) { + private void addSummaryLinks(Content target, boolean nested) { switch (documentedPage) { case MODULE, PACKAGE, CLASS, HELP -> { List listContents = subNavLinks.getSubNavLinks() @@ -367,11 +367,11 @@ public class Navigation { default -> Text.EMPTY; }; if (nested) { - tree.add(HtmlTree.LI(HtmlTree.P(label)) + target.add(HtmlTree.LI(HtmlTree.P(label)) .add(new HtmlTree(TagName.UL).add(listContents))); } else { - tree.add(HtmlTree.LI(label).add(Entity.NO_BREAK_SPACE)); - addListToNav(listContents, tree); + target.add(HtmlTree.LI(label).add(Entity.NO_BREAK_SPACE)); + addListToNav(listContents, target); } } } @@ -381,10 +381,10 @@ public class Navigation { /** * Adds the detail links to sub-navigation. * - * @param tree the content tree to which the links will be added + * @param target the content to which the links will be added * @param nested whether to create a flat or nested list */ - private void addDetailLinks(Content tree, boolean nested) { + private void addDetailLinks(Content target, boolean nested) { if (documentedPage == PageMode.CLASS) { List listContents = new ArrayList<>(); VisibleMemberTable vmt = configuration.getVisibleMemberTable((TypeElement) element); @@ -394,14 +394,14 @@ public class Navigation { } if (!listContents.isEmpty()) { if (nested) { - Content li = HtmlTree.LI(HtmlTree.P(contents.detailLabel)); + var li = HtmlTree.LI(HtmlTree.P(contents.detailLabel)); li.add(new HtmlTree(TagName.UL).add(listContents)); - tree.add(li); + target.add(li); } else { - Content li = HtmlTree.LI(contents.detailLabel); + var li = HtmlTree.LI(contents.detailLabel); li.add(Entity.NO_BREAK_SPACE); - tree.add(li); - addListToNav(listContents, tree); + target.add(li); + addListToNav(listContents, target); } } } @@ -427,15 +427,15 @@ public class Navigation { }); } - private void addContentToList(List listContents, Content tree) { - listContents.add(HtmlTree.LI(tree)); + private void addContentToList(List listContents, Content source) { + listContents.add(HtmlTree.LI(source)); } - private void addContentToTree(Content tree, Content content) { - tree.add(HtmlTree.LI(content)); + private void addItemToList(Content list, Content item) { + list.add(HtmlTree.LI(item)); } - private void addListToNav(List listContents, Content tree) { + private void addListToNav(List listContents, Content target) { int count = 0; for (Content liContent : listContents) { if (count < listContents.size() - 1) { @@ -443,51 +443,51 @@ public class Navigation { liContent.add("|"); liContent.add(Entity.NO_BREAK_SPACE); } - tree.add(liContent); + target.add(liContent); count++; } } - private void addActivePageLink(Content tree, Content label, boolean display) { + private void addActivePageLink(Content target, Content label, boolean display) { if (display) { - tree.add(HtmlTree.LI(HtmlStyle.navBarCell1Rev, label)); + target.add(HtmlTree.LI(HtmlStyle.navBarCell1Rev, label)); } } - private void addPageLabel(Content tree, Content label, boolean display) { + private void addPageLabel(Content target, Content label, boolean display) { if (display) { - tree.add(HtmlTree.LI(label)); + target.add(HtmlTree.LI(label)); } } - private void addOverviewLink(Content tree) { + private void addOverviewLink(Content target) { if (options.createOverview()) { - tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.INDEX), + target.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.INDEX), contents.overviewLabel, ""))); } } - private void addModuleLink(Content tree) { + private void addModuleLink(Content target) { if (configuration.showModules) { if (configuration.modules.size() == 1) { ModuleElement mdle = configuration.modules.first(); boolean included = configuration.utils.isIncluded(mdle); - tree.add(HtmlTree.LI((included) + target.add(HtmlTree.LI((included) ? links.createLink(pathToRoot.resolve(configuration.docPaths.moduleSummary(mdle)), contents.moduleLabel, "") : contents.moduleLabel)); } else if (!configuration.modules.isEmpty()) { - addPageLabel(tree, contents.moduleLabel, true); + addPageLabel(target, contents.moduleLabel, true); } } } - private void addModuleOfElementLink(Content tree) { + private void addModuleOfElementLink(Content target) { if (configuration.showModules) { - tree.add(HtmlTree.LI(navLinkModule)); + target.add(HtmlTree.LI(navLinkModule)); } } - private void addPackageLink(Content tree) { + private void addPackageLink(Content target) { if (configuration.packages.size() == 1) { PackageElement packageElement = configuration.packages.first(); boolean included = packageElement != null && configuration.utils.isIncluded(packageElement); @@ -500,66 +500,66 @@ public class Navigation { } } if (included || packageElement == null) { - tree.add(HtmlTree.LI(links.createLink( + target.add(HtmlTree.LI(links.createLink( pathToRoot.resolve(configuration.docPaths.forPackage(packageElement).resolve(DocPaths.PACKAGE_SUMMARY)), contents.packageLabel))); } else { DocLink crossPkgLink = configuration.extern.getExternalLink( packageElement, pathToRoot, DocPaths.PACKAGE_SUMMARY.getPath()); if (crossPkgLink != null) { - tree.add(HtmlTree.LI(links.createLink(crossPkgLink, contents.packageLabel))); + target.add(HtmlTree.LI(links.createLink(crossPkgLink, contents.packageLabel))); } else { - tree.add(HtmlTree.LI(contents.packageLabel)); + target.add(HtmlTree.LI(contents.packageLabel)); } } } else if (!configuration.packages.isEmpty()) { - addPageLabel(tree, contents.packageLabel, true); + addPageLabel(target, contents.packageLabel, true); } } - private void addPackageOfElementLink(Content tree) { - tree.add(HtmlTree.LI(links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), + private void addPackageOfElementLink(Content target) { + target.add(HtmlTree.LI(links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), contents.packageLabel))); } - private void addPackageSummaryLink(Content tree) { - tree.add(HtmlTree.LI(links.createLink(DocPaths.PACKAGE_SUMMARY, contents.packageLabel))); + private void addPackageSummaryLink(Content target) { + target.add(HtmlTree.LI(links.createLink(DocPaths.PACKAGE_SUMMARY, contents.packageLabel))); } - private void addTreeLink(Content tree) { + private void addTreeLink(Content target) { if (options.createTree()) { List packages = new ArrayList<>(configuration.getSpecifiedPackageElements()); DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty() ? pathToRoot.resolve(configuration.docPaths.forPackage(packages.get(0)).resolve(DocPaths.PACKAGE_TREE)) : pathToRoot.resolve(DocPaths.OVERVIEW_TREE); - tree.add(HtmlTree.LI(links.createLink(docPath, contents.treeLabel, ""))); + target.add(HtmlTree.LI(links.createLink(docPath, contents.treeLabel, ""))); } } - private void addDeprecatedLink(Content tree) { + private void addDeprecatedLink(Content target) { if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.DEPRECATED)) { - tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), + target.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), contents.deprecatedLabel, ""))); } } - private void addPreviewLink(Content tree) { + private void addPreviewLink(Content target) { if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.PREVIEW)) { - tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.PREVIEW_LIST), + target.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.PREVIEW_LIST), contents.previewLabel, ""))); } } - private void addNewLink(Content tree) { + private void addNewLink(Content target) { if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.NEW)) { - tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.NEW_LIST), + target.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.NEW_LIST), contents.newLabel, ""))); } } - private void addIndexLink(Content tree) { + private void addIndexLink(Content target) { if (options.createIndex()) { - tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve( + target.add(HtmlTree.LI(links.createLink(pathToRoot.resolve( (options.splitIndex() ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)) : DocPaths.INDEX_ALL)), @@ -567,7 +567,7 @@ public class Navigation { } } - private void addHelpLink(Content tree) { + private void addHelpLink(Content target) { if (!options.noHelp()) { String helpfile = options.helpFile(); DocPath helpfilenm; @@ -577,23 +577,23 @@ public class Navigation { DocFile file = DocFile.createFileForInput(configuration, helpfile); helpfilenm = DocPath.create(file.getName()); } - tree.add(HtmlTree.LI(links.createLink( + target.add(HtmlTree.LI(links.createLink( new DocLink(pathToRoot.resolve(helpfilenm), htmlIds.forPage(documentedPage).name()), contents.helpLabel, ""))); } } - private void addSearch(Content tree) { + private void addSearch(Content target) { String reset = "reset"; - HtmlTree inputText = HtmlTree.INPUT("text", HtmlIds.SEARCH_INPUT) + var inputText = HtmlTree.INPUT("text", HtmlIds.SEARCH_INPUT) .put(HtmlAttr.PLACEHOLDER, searchPlaceholder); - HtmlTree inputReset = HtmlTree.INPUT(reset, HtmlIds.RESET_BUTTON) + var inputReset = HtmlTree.INPUT(reset, HtmlIds.RESET_BUTTON) .put(HtmlAttr.VALUE, reset); - HtmlTree searchDiv = HtmlTree.DIV(HtmlStyle.navListSearch, + var searchDiv = HtmlTree.DIV(HtmlStyle.navListSearch, HtmlTree.LABEL(HtmlIds.SEARCH_INPUT.name(), searchLabel)); searchDiv.add(inputText); searchDiv.add(inputReset); - tree.add(searchDiv); + target.add(searchDiv); } /** @@ -605,12 +605,12 @@ public class Navigation { if (options.noNavbar()) { return new ContentBuilder(); } - Content tree = HtmlTree.NAV(); + var navigationBar = HtmlTree.NAV(); - HtmlTree navDiv = new HtmlTree(TagName.DIV); + var navDiv = new HtmlTree(TagName.DIV); Content skipNavLinks = contents.getContent("doclet.Skip_navigation_links"); String toggleNavLinks = configuration.getDocResources().getText("doclet.Toggle_navigation_links"); - tree.add(MarkerComments.START_OF_TOP_NAVBAR); + navigationBar.add(MarkerComments.START_OF_TOP_NAVBAR); navDiv.setStyle(HtmlStyle.topNav) .setId(HtmlIds.NAVBAR_TOP) .add(new HtmlTree(TagName.BUTTON).setId(HtmlIds.NAVBAR_TOGGLE_BUTTON) @@ -626,29 +626,29 @@ public class Navigation { Content aboutContent = userHeader; boolean addSearch = options.createIndex(); - Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, aboutContent); + var aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, aboutContent); navDiv.add(aboutDiv); - HtmlTree navList = new HtmlTree(TagName.UL) + var navList = new HtmlTree(TagName.UL) .setId(HtmlIds.NAVBAR_TOP_FIRSTROW) .setStyle(HtmlStyle.navList) .put(HtmlAttr.TITLE, rowListTitle); addMainNavLinks(navList); navDiv.add(navList); - HtmlTree ulNavSummaryRight = HtmlTree.UL(HtmlStyle.subNavListSmall); + var ulNavSummaryRight = HtmlTree.UL(HtmlStyle.subNavListSmall); addSummaryLinks(ulNavSummaryRight, true); addDetailLinks(ulNavSummaryRight, true); navDiv.add(ulNavSummaryRight); - tree.add(navDiv); + navigationBar.add(navDiv); - HtmlTree subDiv = HtmlTree.DIV(HtmlStyle.subNav); + var subDiv = HtmlTree.DIV(HtmlStyle.subNav); - HtmlTree div = new HtmlTree(TagName.DIV).setId(HtmlIds.NAVBAR_SUB_LIST); + var div = new HtmlTree(TagName.DIV).setId(HtmlIds.NAVBAR_SUB_LIST); // Add the summary links if present. - HtmlTree ulNavSummary = HtmlTree.UL(HtmlStyle.subNavList); + var ulNavSummary = HtmlTree.UL(HtmlStyle.subNavList); addSummaryLinks(ulNavSummary, false); div.add(ulNavSummary); // Add the detail links if present. - HtmlTree ulNavDetail = HtmlTree.UL(HtmlStyle.subNavList); + var ulNavDetail = HtmlTree.UL(HtmlStyle.subNavList); addDetailLinks(ulNavDetail, false); div.add(ulNavDetail); subDiv.add(div); @@ -656,12 +656,12 @@ public class Navigation { if (addSearch) { addSearch(subDiv); } - tree.add(subDiv); + navigationBar.add(subDiv); - tree.add(MarkerComments.END_OF_TOP_NAVBAR); - tree.add(HtmlTree.SPAN(HtmlStyle.skipNav, HtmlTree.EMPTY) + navigationBar.add(MarkerComments.END_OF_TOP_NAVBAR); + navigationBar.add(HtmlTree.SPAN(HtmlStyle.skipNav, HtmlTree.EMPTY) .setId(HtmlIds.SKIP_NAVBAR_TOP)); - return tree; + return navigationBar; } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java index c92e327691c462f3e4094c48b5b1c3512d396f42..e24e9000ff95c612c39fb8d069e7b79b19cdd9f9 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.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 @@ -60,11 +60,11 @@ public class NestedClassWriterImpl extends AbstractMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, - Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_NESTED_CLASS_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + Content content) { + content.add(MarkerComments.START_OF_NESTED_CLASS_SUMMARY); + Content memberContent = new ContentBuilder(); + writer.addSummaryHeader(this, memberContent); + return memberContent; } @Override @@ -74,15 +74,15 @@ public class NestedClassWriterImpl extends AbstractMemberWriter } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.nestedClassSummary); - memberTree.add(label); + content.add(label); } @Override public TableHeader getSummaryTableHeader(Element member) { - Content label = utils.isInterface(member) ? + Content label = utils.isPlainInterface(member) ? contents.interfaceLabel : contents.classLabel; return new TableHeader(contents.modifierAndTypeLabel, label, contents.descriptionLabel); @@ -100,44 +100,44 @@ public class NestedClassWriterImpl extends AbstractMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { Content classLink = writer.getPreQualifiedClassLink(HtmlLinkInfo.Kind.MEMBER, typeElement); Content label; if (options.summarizeOverriddenMethods()) { - label = Text.of(utils.isInterface(typeElement) + label = Text.of(utils.isPlainInterface(typeElement) ? resources.getText("doclet.Nested_Classes_Interfaces_Declared_In_Interface") : resources.getText("doclet.Nested_Classes_Interfaces_Declared_In_Class")); } else { - label = Text.of(utils.isInterface(typeElement) + label = Text.of(utils.isPlainInterface(typeElement) ? resources.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Interface") : resources.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class")); } - HtmlTree labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, label); + var labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, label); labelHeading.setId(htmlIds.forInheritedClasses(typeElement)); labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); - inheritedTree.add(labelHeading); + content.add(labelHeading); } @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member, - Content tdSummary) { + Content content) { Content memberLink = writer.getLink(new HtmlLinkInfo(configuration, context, (TypeElement)member) .style(HtmlStyle.typeNameLink)); - Content code = HtmlTree.CODE(memberLink); - tdSummary.add(code); + var code = HtmlTree.CODE(memberLink); + content.add(code); } @Override - protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { - linksTree.add( + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content target) { + target.add( writer.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER, (TypeElement)member))); } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { - addModifierAndType(member, null, tdSummaryType); + protected void addSummaryType(Element member, Content content) { + addModifiersAndType(member, null, content); } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java index 11bb4d6def59b45572f8346c9492de7859d617ff..ef0226e36f3deb40f55dc8af69815a7c78165428 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.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 @@ -82,10 +82,10 @@ public class PackageIndexWriter extends AbstractOverviewIndexWriter { /** * Adds the packages list to the documentation tree. * - * @param main the documentation tree to which the packages list will be added + * @param target the content to which the packages list will be added */ @Override - protected void addIndex(Content main) { + protected void addIndex(Content target) { Map> groupPackageMap = configuration.group.groupPackages(packages); @@ -113,7 +113,7 @@ public class PackageIndexWriter extends AbstractOverviewIndexWriter { } } - main.add(table); + target.add(table); if (table.needsScript()) { getMainBodyScript().append(table.getScript()); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java index 9618be166f994cb766ae7467d2a9099ad27f3c35..a0d6730c652f7aebafab2bd0d99d0f9b1f64bbdb 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java @@ -90,7 +90,8 @@ public class PackageTreeWriter extends AbstractTreeWriter { } /** - * Generate a separate tree file for each package. + * Generate a separate tree file. + * * @throws DocFileIOException if there is a problem generating the package tree file */ protected void generatePackageTreeFile() throws DocFileIOException { @@ -100,11 +101,11 @@ public class PackageTreeWriter extends AbstractTreeWriter { ? contents.getContent("doclet.Hierarchy_For_Unnamed_Package") : contents.getContent("doclet.Hierarchy_For_Package", getLocalizedPackageName(packageElement)); - Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, headContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); if (configuration.packages.size() > 1) { - addLinkToMainTree(div); + addLinkToAllPackages(div); } mainContent.add(div); addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", mainContent); @@ -120,14 +121,14 @@ public class PackageTreeWriter extends AbstractTreeWriter { /** * Get the package tree header. * - * @return a content tree for the header + * @return the package tree header */ protected HtmlTree getPackageTreeHeader() { String packageName = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); String title = packageName + " " + resources.getText("doclet.Window_Class_Hierarchy"); - HtmlTree bodyTree = getBody(getWindowTitle(title)); + HtmlTree body = getBody(getWindowTitle(title)); bodyContents.setHeader(getHeader(PageMode.TREE, packageElement)); - return bodyTree; + return body; } @Override @@ -141,14 +142,16 @@ public class PackageTreeWriter extends AbstractTreeWriter { /** * Add a link to the tree for all the packages. * - * @param div the content tree to which the link will be added + * @param target the content to which the link will be added */ - protected void addLinkToMainTree(Content div) { - Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, + protected void addLinkToAllPackages(Content target) { + var span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, contents.packageHierarchies); - div.add(span); - HtmlTree ul = HtmlTree.UL(HtmlStyle.horizontal); - ul.add(getNavLinkMainTree(resources.getText("doclet.All_Packages"))); - div.add(ul); + target.add(span); + var ul = HtmlTree.UL(HtmlStyle.horizontal); + // TODO the link should be more specific: + // it should point to the "all packages" section of the overview tree + ul.add(getNavLinkToOverviewTree(resources.getText("doclet.All_Packages"))); + target.add(ul); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java index 1c44a1308685a2870f036d1bcc8608b4d9af6ba3..22dbe6c8c7e652648cca12ddbb0a0a7b762d82b3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -116,7 +116,7 @@ public class PackageUseWriter extends SubWriterHolderWriter { * @throws DocFileIOException if there is a problem generating the package use page */ protected void generatePackageUseFile() throws DocFileIOException { - HtmlTree body = getPackageUseHeader(); + HtmlTree body = getBody(); Content mainContent = new ContentBuilder(); if (usingPackageToUsedClasses.isEmpty()) { mainContent.add(contents.getContent("doclet.ClassUse_No.usage.of.0", getLocalizedPackageName(packageElement))); @@ -134,23 +134,23 @@ public class PackageUseWriter extends SubWriterHolderWriter { /** * Add the package use information. * - * @param contentTree the content tree to which the package use information will be added + * @param content the content to which the package use information will be added */ - protected void addPackageUse(Content contentTree) { - Content content = new ContentBuilder(); + protected void addPackageUse(Content content) { + Content c = new ContentBuilder(); if (configuration.packages.size() > 1) { - addPackageList(content); + addPackageList(c); } - addClassList(content); - contentTree.add(content); + addClassList(c); + content.add(c); } /** * Add the list of packages that use the given package. * - * @param contentTree the content tree to which the package list will be added + * @param content the content to which the package list will be added */ - protected void addPackageList(Content contentTree) { + protected void addPackageList(Content content) { Content caption = contents.getContent( "doclet.ClassUse_Packages.that.use.0", getPackageLink(packageElement, getLocalizedPackageName(packageElement))); @@ -170,21 +170,21 @@ public class PackageUseWriter extends SubWriterHolderWriter { } table.addRow(packageLink, summary); } - contentTree.add(table); + content.add(table); } /** * Add the list of classes that use the given package. * - * @param contentTree the content tree to which the class list will be added + * @param content the content to which the class list will be added */ - protected void addClassList(Content contentTree) { + protected void addClassList(Content content) { TableHeader classTableHeader = new TableHeader( contents.classLabel, contents.descriptionLabel); - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList); + var ul = HtmlTree.UL(HtmlStyle.blockList); for (String packageName : usingPackageToUsedClasses.keySet()) { PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); - HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail) + var section = HtmlTree.SECTION(HtmlStyle.detail) .setId(htmlIds.forPackage(usingPackage)); Content caption = contents.getContent( "doclet.ClassUse_Classes.in.0.used.by.1", @@ -208,30 +208,28 @@ public class PackageUseWriter extends SubWriterHolderWriter { section.add(table); ul.add(HtmlTree.LI(section)); } - Content li = HtmlTree.SECTION(HtmlStyle.packageUses, ul); - contentTree.add(li); + var li = HtmlTree.SECTION(HtmlStyle.packageUses, ul); + content.add(li); } /** - * Get the header for the package use listing. - * - * @return a content tree representing the package use header + * {@return the package use HTML BODY element} */ - private HtmlTree getPackageUseHeader() { + private HtmlTree getBody() { String packageText = resources.getText("doclet.Package"); String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name); - HtmlTree bodyTree = getBody(getWindowTitle(title)); + HtmlTree body = getBody(getWindowTitle(title)); ContentBuilder headingContent = new ContentBuilder(); headingContent.add(contents.getContent("doclet.ClassUse_Title", packageText)); headingContent.add(new HtmlTree(TagName.BR)); headingContent.add(name); - Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, headingContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); bodyContents.setHeader(getHeader(PageMode.USE, packageElement)) .addMainContent(div); - return bodyTree; + return body; } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java index 231ab6c50e2a3e357ee503005e7c74a1a1c9507e..e8ac645e5ec4053433a39a8f105580df2f1e1091 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -77,9 +77,9 @@ public class PackageWriterImpl extends HtmlDocletWriter private SortedSet allClasses; /** - * The HTML tree for section tag. + * The HTML element for the section tag being written. */ - protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder()); + private final HtmlTree section = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder()); private final BodyContents bodyContents = new BodyContents(); @@ -110,12 +110,12 @@ public class PackageWriterImpl extends HtmlDocletWriter @Override public Content getPackageHeader() { String packageName = getLocalizedPackageName(packageElement).toString(); - HtmlTree bodyTree = getBody(getWindowTitle(packageName)); - HtmlTree div = HtmlTree.DIV(HtmlStyle.header); + HtmlTree body = getBody(getWindowTitle(packageName)); + var div = HtmlTree.DIV(HtmlStyle.header); if (configuration.showModules) { ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); - Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel); - Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); + var classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel); + var moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); moduleNameDiv.add(Entity.NO_BREAK_SPACE); moduleNameDiv.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName().toString()))); @@ -126,12 +126,12 @@ public class PackageWriterImpl extends HtmlDocletWriter packageHead.add(contents.packageLabel).add(" "); } packageHead.add(packageName); - Content tHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var tHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, packageHead); div.add(tHeading); bodyContents.setHeader(getHeader(PageMode.PACKAGE, packageElement)) .addMainContent(div); - return bodyTree; + return body; } @Override @@ -205,14 +205,14 @@ public class PackageWriterImpl extends HtmlDocletWriter /** * Add the package deprecation information to the documentation tree. * - * @param div the content tree to which the deprecation information will be added + * @param div the content to which the deprecation information will be added */ public void addDeprecationInfo(Content div) { List deprs = utils.getDeprecatedTrees(packageElement); if (utils.isDeprecated(packageElement)) { CommentHelper ch = utils.getCommentHelper(packageElement); - HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); - Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement)); + var deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); + var deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { List commentTags = ch.getDescription(deprs.get(0)); @@ -230,33 +230,33 @@ public class PackageWriterImpl extends HtmlDocletWriter } @Override - public void addRelatedPackagesSummary(Content summaryContentTree) { + public void addRelatedPackagesSummary(Content summaryContent) { boolean showModules = configuration.showModules && hasRelatedPackagesInOtherModules(relatedPackages); TableHeader tableHeader= showModules ? new TableHeader(contents.moduleLabel, contents.packageLabel, contents.descriptionLabel) : new TableHeader(contents.packageLabel, contents.descriptionLabel); addPackageSummary(relatedPackages, contents.relatedPackages, tableHeader, - summaryContentTree, showModules); + summaryContent, showModules); } /** - * Add all types to the content tree. + * Add all types to the content. * - * @param summaryContentTree HtmlTree content to which the links will be added + * @param target the content to which the links will be added */ - public void addAllClassesAndInterfacesSummary(Content summaryContentTree) { + public void addAllClassesAndInterfacesSummary(Content target) { Table table = new Table(HtmlStyle.summaryTable) .setHeader(new TableHeader(contents.classLabel, contents.descriptionLabel)) .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast) .setId(HtmlIds.CLASS_SUMMARY) .setDefaultTab(contents.allClassesAndInterfacesLabel) - .addTab(contents.interfaces, utils::isInterface) - .addTab(contents.classes, e -> utils.isOrdinaryClass((TypeElement)e)) + .addTab(contents.interfaces, utils::isPlainInterface) + .addTab(contents.classes, e -> utils.isNonThrowableClass((TypeElement)e)) .addTab(contents.enums, utils::isEnum) .addTab(contents.records, e -> utils.isRecord((TypeElement)e)) .addTab(contents.exceptionClasses, e -> utils.isThrowable((TypeElement)e)) - .addTab(contents.annotationTypes, utils::isAnnotationType); + .addTab(contents.annotationTypes, utils::isAnnotationInterface); for (TypeElement typeElement : allClasses) { if (typeElement != null && utils.isCoreClass(typeElement)) { Content classLink = getLink(new HtmlLinkInfo( @@ -276,7 +276,7 @@ public class PackageWriterImpl extends HtmlDocletWriter } } if (!table.isEmpty()) { - summaryContentTree.add(HtmlTree.LI(table)); + target.add(HtmlTree.LI(table)); if (table.needsScript()) { getMainBodyScript().append(table.getScript()); } @@ -284,7 +284,7 @@ public class PackageWriterImpl extends HtmlDocletWriter } public void addPackageSummary(List packages, Content label, - TableHeader tableHeader, Content summaryContentTree, + TableHeader tableHeader, Content summaryContent, boolean showModules) { if (!packages.isEmpty()) { Table table = new Table(HtmlStyle.summaryTable) @@ -299,7 +299,7 @@ public class PackageWriterImpl extends HtmlDocletWriter for (PackageElement pkg : packages) { Content packageLink = getPackageLink(pkg, Text.of(pkg.getQualifiedName())); - Content moduleLink = HtmlTree.EMPTY; + var moduleLink = HtmlTree.EMPTY; if (showModules) { ModuleElement module = (ModuleElement) pkg.getEnclosingElement(); if (module != null && !module.isUnnamed()) { @@ -323,37 +323,35 @@ public class PackageWriterImpl extends HtmlDocletWriter table.addRow(packageLink, description); } } - summaryContentTree.add(HtmlTree.LI(table)); + summaryContent.add(HtmlTree.LI(table)); } } @Override - public void addPackageDescription(Content packageContentTree) { - addPreviewInfo(packageElement, packageContentTree); + public void addPackageDescription(Content packageContent) { + addPreviewInfo(packageElement, packageContent); if (!utils.getBody(packageElement).isEmpty()) { - HtmlTree tree = sectionTree; - tree.setId(HtmlIds.PACKAGE_DESCRIPTION); - addDeprecationInfo(tree); - addInlineComment(packageElement, tree); + section.setId(HtmlIds.PACKAGE_DESCRIPTION); + addDeprecationInfo(section); + addInlineComment(packageElement, section); } } @Override - public void addPackageTags(Content packageContentTree) { - Content htmlTree = sectionTree; - addTagsInfo(packageElement, htmlTree); - packageContentTree.add(sectionTree); + public void addPackageTags(Content packageContent) { + addTagsInfo(packageElement, section); + packageContent.add(section); } @Override - public void addPackageSignature(Content packageContentTree) { - packageContentTree.add(new HtmlTree(TagName.HR)); - packageContentTree.add(Signatures.getPackageSignature(packageElement, this)); + public void addPackageSignature(Content packageContent) { + packageContent.add(new HtmlTree(TagName.HR)); + packageContent.add(Signatures.getPackageSignature(packageElement, this)); } @Override - public void addPackageContent(Content packageContentTree) { - bodyContents.addMainContent(packageContentTree); + public void addPackageContent(Content packageContent) { + bodyContents.addMainContent(packageContent); } @Override @@ -362,17 +360,17 @@ public class PackageWriterImpl extends HtmlDocletWriter } @Override - public void printDocument(Content contentTree) throws DocFileIOException { + public void printDocument(Content content) throws DocFileIOException { String description = getDescription("declaration", packageElement); List localStylesheets = getLocalStylesheets(packageElement); - contentTree.add(bodyContents); + content.add(bodyContents); printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement), - description, localStylesheets, contentTree); + description, localStylesheets, content); } @Override - public Content getPackageSummary(Content summaryContentTree) { - return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree); + public Content getPackageSummary(Content summaryContent) { + return HtmlTree.SECTION(HtmlStyle.summary, summaryContent); } private boolean hasRelatedPackagesInOtherModules(List relatedPackages) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java index 9ff02bdd8f5b47c964e5970a0f627a701f99bcc9..0ea90930d1ff9e7169c6395ad2062c738ecfb64e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.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 @@ -54,11 +54,11 @@ public class PropertyWriterImpl extends AbstractMemberWriter } @Override - public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { - memberSummaryTree.add(MarkerComments.START_OF_PROPERTY_SUMMARY); - Content memberTree = new ContentBuilder(); - writer.addSummaryHeader(this, memberTree); - return memberTree; + public Content getMemberSummaryHeader(TypeElement typeElement, Content content) { + content.add(MarkerComments.START_OF_PROPERTY_SUMMARY); + Content memberContent = new ContentBuilder(); + writer.addSummaryHeader(this, memberContent); + return memberContent; } @Override @@ -68,22 +68,22 @@ public class PropertyWriterImpl extends AbstractMemberWriter } @Override - public Content getPropertyDetailsTreeHeader(Content memberDetailsTree) { - memberDetailsTree.add(MarkerComments.START_OF_PROPERTY_DETAILS); - Content propertyDetailsTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, + public Content getPropertyDetailsHeader(Content memberDetails) { + memberDetails.add(MarkerComments.START_OF_PROPERTY_DETAILS); + Content propertyDetailsContent = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.propertyDetailsLabel); - propertyDetailsTree.add(heading); - return propertyDetailsTree; + propertyDetailsContent.add(heading); + return propertyDetailsContent; } @Override - public Content getPropertyDocTreeHeader(ExecutableElement property) { - Content propertyDocTree = new ContentBuilder(); - Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, + public Content getPropertyHeaderContent(ExecutableElement property) { + Content content = new ContentBuilder(); + var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING, Text.of(utils.getPropertyLabel(name(property)))); - propertyDocTree.add(heading); - return HtmlTree.SECTION(HtmlStyle.detail, propertyDocTree) + content.add(heading); + return HtmlTree.SECTION(HtmlStyle.detail, content) .setId(htmlIds.forProperty(property)); } @@ -96,20 +96,20 @@ public class PropertyWriterImpl extends AbstractMemberWriter } @Override - public void addDeprecated(ExecutableElement property, Content propertyDocTree) { + public void addDeprecated(ExecutableElement property, Content propertyContent) { } @Override - public void addPreview(ExecutableElement property, Content propertyDocTree) { + public void addPreview(ExecutableElement property, Content content) { } @Override - public void addComments(ExecutableElement property, Content propertyDocTree) { + public void addComments(ExecutableElement property, Content propertyContent) { TypeElement holder = (TypeElement)property.getEnclosingElement(); if (!utils.getFullBody(property).isEmpty()) { if (holder.equals(typeElement) || (!utils.isPublic(holder) || utils.isLinkable(holder))) { - writer.addInlineComment(property, propertyDocTree); + writer.addInlineComment(property, propertyContent); } else { if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(property)) { Content link = @@ -117,39 +117,39 @@ public class PropertyWriterImpl extends AbstractMemberWriter holder, property, utils.isIncluded(holder) ? holder.getSimpleName() : holder.getQualifiedName()); - Content codeLink = HtmlTree.CODE(link); - Content descriptionFromLabel = HtmlTree.SPAN(HtmlStyle.descriptionFromTypeLabel, + var codeLink = HtmlTree.CODE(link); + var descriptionFromLabel = HtmlTree.SPAN(HtmlStyle.descriptionFromTypeLabel, utils.isClass(holder) ? contents.descriptionFromClassLabel : contents.descriptionFromInterfaceLabel); descriptionFromLabel.add(Entity.NO_BREAK_SPACE); descriptionFromLabel.add(codeLink); - propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descriptionFromLabel)); + propertyContent.add(HtmlTree.DIV(HtmlStyle.block, descriptionFromLabel)); } - writer.addInlineComment(property, propertyDocTree); + writer.addInlineComment(property, propertyContent); } } } @Override - public void addTags(ExecutableElement property, Content propertyDocTree) { - writer.addTagsInfo(property, propertyDocTree); + public void addTags(ExecutableElement property, Content propertyContent) { + writer.addTagsInfo(property, propertyContent); } @Override - public Content getPropertyDetails(Content propertyDetailsTreeHeader, Content propertyDetailsTree) { + public Content getPropertyDetails(Content memberDetailsHeader, Content memberDetails) { return writer.getDetailsListItem( HtmlTree.SECTION(HtmlStyle.propertyDetails) .setId(HtmlIds.PROPERTY_DETAIL) - .add(propertyDetailsTreeHeader) - .add(propertyDetailsTree)); + .add(memberDetailsHeader) + .add(memberDetails)); } @Override - public void addSummaryLabel(Content memberTree) { - Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, + public void addSummaryLabel(Content content) { + var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, contents.propertySummaryLabel); - memberTree.add(label); + content.add(label); } @Override @@ -167,7 +167,7 @@ public class PropertyWriterImpl extends AbstractMemberWriter } @Override - public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + public void addInheritedSummaryLabel(TypeElement typeElement, Content content) { Content classLink = writer.getPreQualifiedClassLink( HtmlLinkInfo.Kind.MEMBER, typeElement); Content label; @@ -180,38 +180,38 @@ public class PropertyWriterImpl extends AbstractMemberWriter ? resources.getText("doclet.Properties_Inherited_From_Class") : resources.getText("doclet.Properties_Inherited_From_Interface")); } - HtmlTree labelHeading = + var labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label) .setId(htmlIds.forInheritedProperties(typeElement)) .add(Entity.NO_BREAK_SPACE) .add(classLink); - inheritedTree.add(labelHeading); + content.add(labelHeading); } @Override protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member, - Content tdSummary) { + Content content) { Content memberLink = writer.getDocLink(context, typeElement, member, Text.of(utils.getPropertyLabel(name(member))), HtmlStyle.memberNameLink, true); - Content code = HtmlTree.CODE(memberLink); - tdSummary.add(code); + var code = HtmlTree.CODE(memberLink); + content.add(code); } @Override - protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content target) { String mname = name(member); Content content = writer.getDocLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member, utils.isProperty(mname) ? utils.getPropertyName(mname) : mname, true); - linksTree.add(content); + target.add(content); } @Override - protected void addSummaryType(Element member, Content tdSummaryType) { - addModifierAndType(member, utils.getReturnType(typeElement, (ExecutableElement)member), tdSummaryType); + protected void addSummaryType(Element member, Content content) { + addModifiersAndType(member, utils.getReturnType(typeElement, (ExecutableElement)member), content); } @Override @@ -220,8 +220,4 @@ public class PropertyWriterImpl extends AbstractMemberWriter utils.getFullyQualifiedName(member)); } - @Override - public Content getMemberTreeHeader(){ - return writer.getMemberTreeHeader(); - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java index 242ebf371999841833b6f5a2fe3aa6d5866c0a33..e5a82e9a0f1e10877b02134e724db2531c41fab1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java @@ -68,24 +68,24 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter * Get the given header. * * @param header the header to write - * @return the body content tree + * @return the body content */ @Override public Content getHeader(String header) { - HtmlTree bodyTree = getBody(getWindowTitle(header)); + HtmlTree body = getBody(getWindowTitle(header)); Content h1Content = Text.of(header); - Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, h1Content); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); bodyContents.setHeader(getHeader(PageMode.SERIALIZED_FORM)) .addMainContent(div); - return bodyTree; + return body; } /** * Get the serialized form summaries header. * - * @return the serialized form summary header tree + * @return the serialized form summaries header */ @Override public Content getSerializedSummariesHeader() { @@ -102,30 +102,18 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter return HtmlTree.SECTION(HtmlStyle.serializedPackageContainer); } - /** - * Get the given package header. - * - * @param packageElement the package element to write - * @return a content tree for the package header - */ @Override public Content getPackageHeader(PackageElement packageElement) { - Content heading = HtmlTree.HEADING_TITLE(Headings.SerializedForm.PACKAGE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.SerializedForm.PACKAGE_HEADING, contents.packageLabel); heading.add(Entity.NO_BREAK_SPACE); heading.add(getPackageLink(packageElement, Text.of(utils.getPackageName(packageElement)))); return heading; } - /** - * Get the serialized class header. - * - * @return a content tree for the serialized class header - */ @Override public Content getClassSerializedHeader() { return HtmlTree.UL(HtmlStyle.blockList); - } /** @@ -139,19 +127,13 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter && !utils.hasHiddenTag(typeElement); } - /** - * Get the serializable class heading. - * - * @param typeElement the class being processed - * @return a content tree for the class header - */ @Override public Content getClassHeader(TypeElement typeElement) { Content classLink = (isVisibleClass(typeElement)) ? getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, typeElement) .label(configuration.getClassName(typeElement))) : Text.of(utils.getFullyQualifiedName(typeElement)); - Content section = HtmlTree.SECTION(HtmlStyle.serializedClassDetails) + var section = HtmlTree.SECTION(HtmlStyle.serializedClassDetails) .setId(htmlIds.forClass(typeElement)); Content superClassLink = typeElement.getSuperclass() != null ? getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.SERIALIZED_FORM, @@ -180,11 +162,6 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter return section; } - /** - * Get the serial UID info header. - * - * @return a content tree for the serial uid info header - */ @Override public Content getSerialUIDInfoHeader() { return HtmlTree.DL(HtmlStyle.nameValue); @@ -195,46 +172,40 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter * * @param header the header that will show up before the UID. * @param serialUID the serial UID to print. - * @param serialUidTree the serial UID content tree to which the serial UID - * content will be added + * @param target the serial UID content to which the serial UID + * content will be added */ @Override public void addSerialUIDInfo(String header, String serialUID, - Content serialUidTree) + Content target) { Content headerContent = Text.of(header); - serialUidTree.add(HtmlTree.DT(headerContent)); + target.add(HtmlTree.DT(headerContent)); Content serialContent = Text.of(serialUID); - serialUidTree.add(HtmlTree.DD(serialContent)); + target.add(HtmlTree.DD(serialContent)); } - /** - * Get the class serialize content header. - * - * @return a content tree for the class serialize content header - */ @Override public Content getClassContentHeader() { return HtmlTree.UL(HtmlStyle.blockList); - } /** - * Add the serialized content tree section. + * Add the serialized content section. * - * @param serializedTreeContent the serialized content tree to be added + * @param source the serialized content to be added */ @Override - public void addSerializedContent(Content serializedTreeContent) { - bodyContents.addMainContent(serializedTreeContent); + public void addSerializedContent(Content source) { + bodyContents.addMainContent(source); } @Override - public void addPackageSerializedTree(Content serializedSummariesTree, - Content packageSerializedTree) + public void addPackageSerialized(Content serializedSummaries, + Content packageSerialized) { - serializedSummariesTree.add(HtmlTree.LI(packageSerializedTree)); + serializedSummaries.add(HtmlTree.LI(packageSerialized)); } /** @@ -246,9 +217,9 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter } @Override - public void printDocument(Content serializedTree) throws DocFileIOException { - serializedTree.add(bodyContents); - printHtmlDocument(null, "serialized forms", serializedTree); + public void printDocument(Content source) throws DocFileIOException { + source.add(bodyContents); + printHtmlDocument(null, "serialized forms", source); if (configuration.mainIndex != null) { configuration.mainIndex.add(IndexItem.of(IndexItem.Category.TAGS, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java index 6b54c48b975a49957834b008fe8b7bc3e5680972..94a45588a800a2188e0130e9633ea020448f6c6c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.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 @@ -46,7 +46,6 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementKindVisitor14; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Set; import java.util.SortedSet; @@ -66,7 +65,7 @@ import static javax.lang.model.element.Modifier.SYNCHRONIZED; public class Signatures { public static Content getModuleSignature(ModuleElement mdle, ModuleWriterImpl moduleWriter) { - Content signature = HtmlTree.DIV(HtmlStyle.moduleSignature); + var signature = HtmlTree.DIV(HtmlStyle.moduleSignature); Content annotations = moduleWriter.getAnnotationInfo(mdle, true); if (!annotations.isEmpty()) { signature.add(HtmlTree.SPAN(HtmlStyle.annotations, annotations)); @@ -76,7 +75,7 @@ public class Signatures { ? "open module" : "module"; signature.add(label); signature.add(" "); - HtmlTree nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); + var nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); nameSpan.add(mdle.getQualifiedName().toString()); signature.add(nameSpan); return signature; @@ -86,13 +85,13 @@ public class Signatures { if (pkg.isUnnamed()) { return Text.EMPTY; } - Content signature = HtmlTree.DIV(HtmlStyle.packageSignature); + var signature = HtmlTree.DIV(HtmlStyle.packageSignature); Content annotations = pkgWriter.getAnnotationInfo(pkg, true); if (!annotations.isEmpty()) { signature.add(HtmlTree.SPAN(HtmlStyle.annotations, annotations)); } signature.add("package "); - HtmlTree nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); + var nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); nameSpan.add(pkg.getQualifiedName().toString()); signature.add(nameSpan); return signature; @@ -106,7 +105,7 @@ public class Signatures { private final HtmlConfiguration configuration; private Content modifiers; - private static final Set previewModifiers = Collections.emptySet(); + private static final Set previewModifiers = Set.of(); TypeSignature(TypeElement typeElement, HtmlDocletWriter writer) { this.typeElement = typeElement; @@ -129,7 +128,7 @@ public class Signatures { } content.add(HtmlTree.SPAN(HtmlStyle.modifiers, modifiers)); - HtmlTree nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); + var nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); Content className = Text.of(utils.getSimpleName(typeElement)); if (configuration.getOptions().linkSource()) { writer.addSrcLink(typeElement, className, nameSpan); @@ -146,10 +145,10 @@ public class Signatures { if (utils.isRecord(typeElement)) { content.add(getRecordComponents()); } - if (!utils.isAnnotationType(typeElement)) { - Content extendsImplements = new HtmlTree(TagName.SPAN) + if (!utils.isAnnotationInterface(typeElement)) { + var extendsImplements = new HtmlTree(TagName.SPAN) .setStyle(HtmlStyle.extendsImplements); - if (!utils.isInterface(typeElement)) { + if (!utils.isPlainInterface(typeElement)) { TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement); if (superclass != null) { content.add(DocletConstants.NL); @@ -170,7 +169,7 @@ public class Signatures { } if (isFirst) { extendsImplements.add(DocletConstants.NL); - extendsImplements.add(utils.isInterface(typeElement) ? "extends " : "implements "); + extendsImplements.add(utils.isPlainInterface(typeElement) ? "extends " : "implements "); isFirst = false; } else { extendsImplements.add(", "); @@ -190,7 +189,7 @@ public class Signatures { .filter(t -> utils.isLinkable(utils.asTypeElement(t))) .toList(); if (!linkablePermits.isEmpty()) { - Content permitsSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.permits); + var permitsSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.permits); boolean isFirst = true; for (TypeMirror type : linkablePermits) { if (isFirst) { @@ -379,7 +378,7 @@ public class Signatures { /** * Set the type parameters for an executable member. * - * @param typeParameters the content tree containing the type parameters to add. + * @param typeParameters the type parameters to add. * @return this instance */ MemberSignature setTypeParameters(Content typeParameters) { @@ -390,7 +389,7 @@ public class Signatures { /** * Set the return type for an executable member. * - * @param returnType the content tree containing the return type to add. + * @param returnType the return type to add. * @return this instance */ MemberSignature setReturnType(Content returnType) { @@ -412,33 +411,33 @@ public class Signatures { /** * Set the parameter information of an executable member. * - * @param paramTree the content tree containing the parameter information. + * @param content the parameter information. * @return this instance */ - MemberSignature setParameters(Content paramTree) { - this.parameters = paramTree; + MemberSignature setParameters(Content content) { + this.parameters = content; return this; } /** * Set the exception information of an executable member. * - * @param exceptionTree the content tree containing the exception information + * @param content the exception information * @return this instance */ - MemberSignature setExceptions(Content exceptionTree) { - this.exceptions = exceptionTree; + MemberSignature setExceptions(Content content) { + this.exceptions = content; return this; } /** * Set the annotation information of a member. * - * @param annotationTree the content tree containing the exception information + * @param content the exception information * @return this instance */ - MemberSignature setAnnotations(Content annotationTree) { - this.annotations = annotationTree; + MemberSignature setAnnotations(Content content) { + this.annotations = content; return this; } @@ -473,7 +472,7 @@ public class Signatures { } // Name - HtmlTree nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); + var nameSpan = new HtmlTree(TagName.SPAN).setStyle(HtmlStyle.elementName); if (memberWriter.options.linkSource()) { Content name = Text.of(memberWriter.name(element)); memberWriter.writer.addSrcLink(element, name, nameSpan); @@ -491,12 +490,12 @@ public class Signatures { } /** - * Adds the modifier for the member. The modifiers are ordered as specified + * Adds the modifiers for the member. The modifiers are ordered as specified * by The Java Language Specification. * - * @param htmlTree the content tree to which the modifier information will be added + * @param target the content to which the modifier information will be added */ - private void appendModifiers(Content htmlTree) { + private void appendModifiers(Content target) { Set set = new TreeSet<>(element.getModifiers()); // remove the ones we really don't need @@ -508,7 +507,7 @@ public class Signatures { // interface methods and fields. if ((utils.isField(element) || utils.isMethod(element))) { Element te = element.getEnclosingElement(); - if (utils.isInterface(te) || utils.isAnnotationType(te)) { + if (utils.isInterface(te)) { // Remove the implicit abstract and public modifiers if (utils.isMethod(element)) { set.remove(ABSTRACT); @@ -518,7 +517,7 @@ public class Signatures { } if (!set.isEmpty()) { String mods = set.stream().map(Modifier::toString).collect(Collectors.joining(" ")); - htmlTree.add(HtmlTree.SPAN(HtmlStyle.modifiers, Text.of(mods))) + target.add(HtmlTree.SPAN(HtmlStyle.modifiers, Text.of(mods))) .add(Entity.NO_BREAK_SPACE); } } @@ -526,30 +525,30 @@ public class Signatures { /** * Appends the type parameter information to the HTML tree. * - * @param htmlTree the HTML tree + * @param target the HTML tree * @param lastLineSeparator index of last line separator in the HTML tree * @return the new index of the last line separator */ - private int appendTypeParameters(Content htmlTree, int lastLineSeparator) { + private int appendTypeParameters(Content target, int lastLineSeparator) { // Apply different wrapping strategies for type parameters // depending of combined length of type parameters and return type. int typeParamLength = typeParameters.charCount(); if (typeParamLength >= TYPE_PARAMS_MAX_INLINE_LENGTH) { - htmlTree.add(HtmlTree.SPAN(HtmlStyle.typeParametersLong, typeParameters)); + target.add(HtmlTree.SPAN(HtmlStyle.typeParametersLong, typeParameters)); } else { - htmlTree.add(HtmlTree.SPAN(HtmlStyle.typeParameters, typeParameters)); + target.add(HtmlTree.SPAN(HtmlStyle.typeParameters, typeParameters)); } - int lineLength = htmlTree.charCount() - lastLineSeparator; + int lineLength = target.charCount() - lastLineSeparator; int newLastLineSeparator = lastLineSeparator; // sum below includes length of modifiers plus type params added above if (lineLength + returnType.charCount() > RETURN_TYPE_MAX_LINE_LENGTH) { - htmlTree.add(DocletConstants.NL); - newLastLineSeparator = htmlTree.charCount(); + target.add(DocletConstants.NL); + newLastLineSeparator = target.charCount(); } else { - htmlTree.add(Entity.NO_BREAK_SPACE); + target.add(Entity.NO_BREAK_SPACE); } return newLastLineSeparator; @@ -558,25 +557,25 @@ public class Signatures { /** * Appends the parameters and exceptions information to the HTML tree. * - * @param htmlTree the HTML tree + * @param target the HTML tree * @param lastLineSeparator the index of the last line separator in the HTML tree */ - private void appendParametersAndExceptions(Content htmlTree, int lastLineSeparator) { + private void appendParametersAndExceptions(Content target, int lastLineSeparator) { // Record current position for indentation of exceptions - int indentSize = htmlTree.charCount() - lastLineSeparator; + int indentSize = target.charCount() - lastLineSeparator; if (parameters.charCount() == 2) { // empty parameters are added without packing - htmlTree.add(parameters); + target.add(parameters); } else { - htmlTree.add(new HtmlTree(TagName.WBR)) + target.add(new HtmlTree(TagName.WBR)) .add(HtmlTree.SPAN(HtmlStyle.parameters, parameters)); } // Exceptions if (exceptions != null && !exceptions.isEmpty()) { CharSequence indent = " ".repeat(Math.max(0, indentSize + 1 - 7)); - htmlTree.add(DocletConstants.NL) + target.add(DocletConstants.NL) .add(indent) .add("throws ") .add(HtmlTree.SPAN(HtmlStyle.exceptions, exceptions)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java index 4efa6a70d229eb80bf471a8b56c6a6c391b8232f..cb0c657c171a52fc06fdc0237fe29e8a2e3c7156 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java @@ -207,8 +207,8 @@ public class SourceToHTMLConverter { .resolve(configuration.docPaths.forPackage(te)) .invert(); Content body = getHeader(); - Content pre = new HtmlTree(TagName.PRE); - try (LineNumberReader reader = new LineNumberReader(r)) { + var pre = new HtmlTree(TagName.PRE); + try (var reader = new LineNumberReader(r)) { while ((line = reader.readLine()) != null) { addLineNo(pre, lineno); addLine(pre, line, lineno); @@ -216,7 +216,7 @@ public class SourceToHTMLConverter { } } addBlankLines(pre); - Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); + var div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); body.add(HtmlTree.MAIN(div)); writeToFile(body, outputdir.resolve(configuration.docPaths.forClass(te)), te); } catch (IOException e) { @@ -240,16 +240,16 @@ public class SourceToHTMLConverter { .setGenerator(HtmlDocletWriter.getGenerator(getClass())) .addDefaultScript(false) .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets()); - Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head, body); - HtmlDocument htmlDocument = new HtmlDocument(htmlTree); + var html = HtmlTree.HTML(configuration.getLocale().getLanguage(), head, body); + HtmlDocument document = new HtmlDocument(html); messages.notice("doclet.Generating_0", path.getPath()); - htmlDocument.write(DocFile.createFileForOutput(configuration, path)); + document.write(DocFile.createFileForOutput(configuration, path)); } /** * Returns a link to the stylesheet file. * - * @param head an HtmlTree to which the stylesheet links will be added + * @param head the content to which the stylesheet links will be added */ public void addStyleSheetProperties(Content head) { String filename = options.stylesheetFile(); @@ -261,18 +261,18 @@ public class SourceToHTMLConverter { stylesheet = DocPaths.STYLESHEET; } DocPath p = relativePath.resolve(stylesheet); - HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", p.getPath(), "Style"); + var link = HtmlTree.LINK("stylesheet", "text/css", p.getPath(), "Style"); head.add(link); addStylesheets(head); } - protected void addStylesheets(Content tree) { + protected void addStylesheets(Content head) { options.additionalStylesheets().forEach(css -> { DocFile file = DocFile.createFileForInput(configuration, css); DocPath cssPath = DocPath.create(file.getName()); - HtmlTree slink = HtmlTree.LINK("stylesheet", "text/css", relativePath.resolve(cssPath).getPath(), - "Style"); - tree.add(slink); + var slink = HtmlTree.LINK("stylesheet", "text/css", relativePath.resolve(cssPath).getPath(), + "Style"); + head.add(slink); }); } @@ -288,11 +288,11 @@ public class SourceToHTMLConverter { /** * Add the line numbers for the source code. * - * @param pre the content tree to which the line number will be added + * @param pre the content to which the line number will be added * @param lineno The line number */ private static void addLineNo(Content pre, int lineno) { - HtmlTree span = new HtmlTree(TagName.SPAN); + var span = new HtmlTree(TagName.SPAN); span.setStyle(HtmlStyle.sourceLineNo); if (lineno < 10) { span.add("00" + Integer.toString(lineno)); @@ -307,13 +307,13 @@ public class SourceToHTMLConverter { /** * Add a line from source to the HTML file that is generated. * - * @param pre the content tree to which the line will be added. + * @param pre the content to which the line will be added. * @param line the string to format. * @param currentLineNo the current number. */ private void addLine(Content pre, String line, int currentLineNo) { if (line != null) { - Content anchor = HtmlTree.SPAN_ID( + var anchor = HtmlTree.SPAN_ID( HtmlIds.forLine(currentLineNo), Text.of(utils.replaceTabs(line))); pre.add(anchor); @@ -324,7 +324,7 @@ public class SourceToHTMLConverter { /** * Add trailing blank lines at the end of the page. * - * @param pre the content tree to which the blank lines will be added. + * @param pre the content to which the blank lines will be added. */ private static void addBlankLines(Content pre) { for (int i = 0; i < NUM_BLANK_LINES; i++) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java index 0a22ce4ae4a1333b0166534658632991167aba35..f783327f5dbe09ca93458e5c8dd2631a279c9936 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java @@ -71,10 +71,10 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * Add the summary header. * * @param mw the writer for the member being documented - * @param memberTree the content tree to which the summary header will be added + * @param memberContent the content to which the summary header will be added */ - public void addSummaryHeader(AbstractMemberWriter mw, Content memberTree) { - mw.addSummaryLabel(memberTree); + public void addSummaryHeader(AbstractMemberWriter mw, Content memberContent) { + mw.addSummaryLabel(memberContent); } /** @@ -82,22 +82,22 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * * @param mw the writer for the member being documented * @param typeElement the te to be documented - * @param inheritedTree the content tree to which the inherited summary header will be added + * @param inheritedContent the content to which the inherited summary header will be added */ public void addInheritedSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement, - Content inheritedTree) { - mw.addInheritedSummaryLabel(typeElement, inheritedTree); + Content inheritedContent) { + mw.addInheritedSummaryLabel(typeElement, inheritedContent); } /** * Add the index comment. * * @param member the member being documented - * @param contentTree the content tree to which the comment will be added + * @param content the content to which the comment will be added */ - protected void addIndexComment(Element member, Content contentTree) { + protected void addIndexComment(Element member, Content content) { List tags = utils.getFirstSentenceTrees(member); - addIndexComment(member, tags, contentTree); + addIndexComment(member, tags, content); } /** @@ -105,41 +105,41 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * * @param member the member being documented * @param firstSentenceTags the first sentence tags for the member to be documented - * @param tdSummary the content tree to which the comment will be added + * @param tdSummaryContent the content to which the comment will be added */ protected void addIndexComment(Element member, List firstSentenceTags, - Content tdSummary) { - addPreviewSummary(member, tdSummary); + Content tdSummaryContent) { + addPreviewSummary(member, tdSummaryContent); List deprs = utils.getDeprecatedTrees(member); Content div; if (utils.isDeprecated(member)) { - Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(member)); + var deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(member)); div = HtmlTree.DIV(HtmlStyle.block, deprLabel); if (!deprs.isEmpty()) { addSummaryDeprecatedComment(member, deprs.get(0), div); } - tdSummary.add(div); + tdSummaryContent.add(div); return; } else { Element te = member.getEnclosingElement(); if (te != null && utils.isTypeElement(te) && utils.isDeprecated(te)) { - Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(te)); + var deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(te)); div = HtmlTree.DIV(HtmlStyle.block, deprLabel); - tdSummary.add(div); + tdSummaryContent.add(div); } } - addSummaryComment(member, firstSentenceTags, tdSummary); + addSummaryComment(member, firstSentenceTags, tdSummaryContent); } /** * Add the summary link for the member. * * @param member the member to be documented - * @param contentTree the content tree to which the link will be added + * @param content the content to which the link will be added */ - public void addSummaryLinkComment(Element member, Content contentTree) { + public void addSummaryLinkComment(Element member, Content content) { List tags = utils.getFirstSentenceTrees(member); - addSummaryLinkComment(member, tags, contentTree); + addSummaryLinkComment(member, tags, content); } /** @@ -147,10 +147,10 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * * @param member the member being documented * @param firstSentenceTags the first sentence tags for the member to be documented - * @param tdSummary the content tree to which the comment will be added + * @param tdSummaryContent the content to which the comment will be added */ - public void addSummaryLinkComment(Element member, List firstSentenceTags, Content tdSummary) { - addIndexComment(member, firstSentenceTags, tdSummary); + public void addSummaryLinkComment(Element member, List firstSentenceTags, Content tdSummaryContent) { + addIndexComment(member, firstSentenceTags, tdSummaryContent); } /** @@ -159,53 +159,49 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * @param mw the writer for the member being documented * @param typeElement the class being documented * @param member the member being documented - * @param isFirst true if its the first link being documented - * @param linksTree the content tree to which the summary will be added + * @param isFirst true if it is the first link being documented + * @param linksContent the content to which the summary will be added */ public void addInheritedMemberSummary(AbstractMemberWriter mw, TypeElement typeElement, Element member, boolean isFirst, - Content linksTree) { + Content linksContent) { if (!isFirst) { - linksTree.add(", "); + linksContent.add(", "); } - mw.addInheritedSummaryLink(typeElement, member, linksTree); + mw.addInheritedSummaryLink(typeElement, member, linksContent); } /** - * Get the document content header tree - * - * @return a content tree the document content header + * {@return the document content header} */ public Content getContentHeader() { return new ContentBuilder(); } /** - * Add the class content tree. + * Add the class content. * - * @param classContentTree class content tree which will be added to the content tree + * @param source class content which will be added to the documentation */ - public void addClassContentTree(Content classContentTree) { - bodyContents.addMainContent(classContentTree); + public void addClassContent(Content source) { + bodyContents.addMainContent(source); } /** - * Add the annotation content tree. + * Add the annotation content. * - * @param annotationContentTree annotation content tree which will be added to the content tree + * @param source annotation content which will be added to the documentation */ - public void addAnnotationContentTree(Content annotationContentTree) { - addClassContentTree(annotationContentTree); + public void addAnnotationContent(Content source) { + addClassContent(source); } /** - * Get the member header tree - * - * @return a content tree for the member header + * {@return the member header} */ - public Content getMemberTreeHeader() { + public Content getMemberHeader() { return HtmlTree.UL(HtmlStyle.blockList); } @@ -249,81 +245,75 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { } /** - * Returns a list to be used for the list of members of a given kind. - * - * @return a list to be used for the list of members of a given kind + * {@return a list to add member items to} */ public Content getMemberList() { return HtmlTree.UL(HtmlStyle.memberList); } /** - * Returns an item for the list of elements of a given kind + * {@return a member item} * - * @param content content for the item - * @return an item for the list of elements of a given kind + * @param member the member to represent as an item */ - public Content getMemberListItem(Content content) { - return HtmlTree.LI(content); + public Content getMemberListItem(Content member) { + return HtmlTree.LI(member); } - public Content getMemberInheritedTree() { + public Content getMemberInherited() { return HtmlTree.DIV(HtmlStyle.inheritedList); } /** - * Adds a section for a summary tree with the given CSS {@code class} and {@code id} attribute. + * Adds a section for a summary with the given CSS {@code class} and {@code id} attribute. * - * @param style the CSS class for the section - * @param htmlId the id for the section - * @param summariesList the list of summary sections to which the summary will be added - * @param content the content tree representing the summary + * @param style the CSS class for the section + * @param htmlId the id for the section + * @param target the list of summary sections to which the summary will be added + * @param source the content representing the summary */ - public void addSummary(HtmlStyle style, HtmlId htmlId, Content summariesList, Content content) { - HtmlTree htmlTree = HtmlTree.SECTION(style, content) + public void addSummary(HtmlStyle style, HtmlId htmlId, Content target, Content source) { + var htmlTree = HtmlTree.SECTION(style, source) .setId(htmlId); - summariesList.add(getSummariesListItem(htmlTree)); + target.add(getSummariesListItem(htmlTree)); } /** - * Get the member tree + * {@return the member content} * - * @param contentTree the tree used to generate the complete member tree - * @return a content tree for the member + * @param content the content used to generate the complete member */ - public Content getMemberTree(Content contentTree) { - return HtmlTree.LI(contentTree); + public Content getMember(Content content) { + return HtmlTree.LI(content); } /** - * Get the member summary tree + * {@return the member summary content} * - * @param contentTree the tree used to generate the member summary tree - * @return a content tree for the member summary + * @param memberContent the content used to generate the member summary */ - public Content getMemberSummaryTree(Content contentTree) { - return HtmlTree.SECTION(HtmlStyle.summary, contentTree); + public Content getMemberSummary(Content memberContent) { + return HtmlTree.SECTION(HtmlStyle.summary, memberContent); } /** - * Get the member details tree + * {@return the member details} * - * @param contentTree the tree used to generate the member details tree - * @return a content tree for the member details + * @param content the content used to generate the member details */ - public Content getMemberDetailsTree(Content contentTree) { - return HtmlTree.SECTION(HtmlStyle.details, contentTree); + public Content getMemberDetailsContent(Content content) { + return HtmlTree.SECTION(HtmlStyle.details, content); } /** - * Get the member tree + * Get the member content * - * @param id the id to be used for the content tree - * @param style the style class to be added to the content tree - * @param contentTree the tree used to generate the complete member tree - * @return the member tree + * @param id the id to be used for the content + * @param style the style class to be added to the content + * @param source the content used to generate the complete member content + * @return the member content */ - public Content getMemberTree(HtmlId id, HtmlStyle style, Content contentTree) { - return HtmlTree.SECTION(style, contentTree).setId(id); + public Content getMember(HtmlId id, HtmlStyle style, Content source) { + return HtmlTree.SECTION(style, source).setId(id); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java index 56bf9b59fe45a54b4fdbb1f5d48a7fa2fe9e5c4f..40210ae7d2cb3ef5b3eb9fb4927773b08c99fc78 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.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 @@ -146,28 +146,28 @@ public class SummaryListWriter extends SubWrite * * @param id the id for the link * @param headingKey - * @param contentTree the content tree to which the index link will be added + * @param content the content to which the index link will be added */ - protected void addIndexLink(HtmlId id, String headingKey, Content contentTree) { - Content li = HtmlTree.LI(links.createLink(id, + protected void addIndexLink(HtmlId id, String headingKey, Content content) { + var li = HtmlTree.LI(links.createLink(id, contents.getContent(headingKey))); - contentTree.add(li); + content.add(li); } /** * Get the contents list. * * @param apiSummary the summary list builder - * @return a content tree for the contents list + * @return the contents list */ public Content getContentsList(L apiSummary) { - Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, headContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); Content headingContent = contents.contentsHeading; div.add(HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, headingContent)); - Content ul = new HtmlTree(TagName.UL); + var ul = new HtmlTree(TagName.UL); addExtraIndexLink(apiSummary, ul); for (SummaryElementKind kind : SummaryElementKind.values()) { if (apiSummary.hasDocumentation(kind)) { @@ -179,29 +179,27 @@ public class SummaryListWriter extends SubWrite } /** - * Get the header for the API Summary Listing. - * - * @return a content tree for the header + * {@return the header for the API Summary listing} */ public HtmlTree getHeader() { String title = resources.getText(titleKey); - HtmlTree bodyTree = getBody(getWindowTitle(title)); + HtmlTree body = getBody(getWindowTitle(title)); bodyContents.setHeader(getHeader(pageMode)); - return bodyTree; + return body; } /** - * Add summary information to the documentation tree + * Add summary information to the documentation * * @param apiList list of API summary elements * @param id the id attribute of the table * @param headingKey the caption for the summary table * @param headerKey table header key for the summary table - * @param contentTree the content tree to which the summary table will be added + * @param content the content to which the summary table will be added */ protected void addSummaryAPI(SortedSet apiList, HtmlId id, String headingKey, String headerKey, - Content contentTree) { + Content content) { if (apiList.size() > 0) { TableHeader tableHeader = new TableHeader( contents.getContent(headerKey), contents.descriptionLabel); @@ -231,7 +229,7 @@ public class SummaryListWriter extends SubWrite table.addRow(e, link, desc); } // note: singleton list - contentTree.add(HtmlTree.UL(HtmlStyle.blockList, HtmlTree.LI(table))); + content.add(HtmlTree.UL(HtmlStyle.blockList, HtmlTree.LI(table))); } } @@ -239,7 +237,7 @@ public class SummaryListWriter extends SubWrite * Add summary text for the given element. * * @param e the element for which the summary text should be added - * @param desc the target to which the text should be added + * @param desc the content to which the text should be added */ protected void addComments(Element e, Content desc) { } @@ -264,7 +262,7 @@ public class SummaryListWriter extends SubWrite * Add an extra optional section to the content. * * @param list the element list - * @param target the target content to which the section should be added + * @param target the content to which the section should be added */ protected void addExtraSection(L list, Content target) { } @@ -273,7 +271,7 @@ public class SummaryListWriter extends SubWrite * Add an extra optional index link. * * @param list the element list - * @param target the target content to which the link should be added + * @param target the content to which the link should be added */ protected void addExtraIndexLink(L list, Content target) { } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SystemPropertiesWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SystemPropertiesWriter.java index 89121697c7e2682cfcd4cf5ec5373f3583cb9150..349841349c12669312f0b7816a9e398923c59e0d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SystemPropertiesWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SystemPropertiesWriter.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 @@ -119,11 +119,11 @@ public class SystemPropertiesWriter extends HtmlDocletWriter { } /** - * Adds all the system properties to the content tree. + * Adds all the system properties to the content. * - * @param content HtmlTree content to which the links will be added + * @param target the content to which the links will be added */ - protected void addSystemProperties(Content content) { + protected void addSystemProperties(Content target) { Map> searchIndexMap = groupSystemProperties(); Content separator = Text.of(", "); Table table = new Table(HtmlStyle.summaryTable) @@ -141,7 +141,7 @@ public class SystemPropertiesWriter extends HtmlDocletWriter { } table.addRow(propertyName, HtmlTree.DIV(HtmlStyle.block, separatedReferenceLinks)); } - content.add(table); + target.add(table); } private Map> groupSystemProperties() { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java index 8cf2e3710f08c4460135dc8b8092415d80f4362b..8870465befbefdc58966e1e1e77a7b3737329015 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java @@ -339,7 +339,7 @@ public class Table extends Content { for (Content c : contents) { HtmlStyle cellStyle = columnStyles.get(colIndex); // Replace invalid content with HtmlTree.EMPTY to make sure the cell isn't dropped - HtmlTree cell = HtmlTree.DIV(cellStyle, c.isValid() ? c : HtmlTree.EMPTY); + var cell = HtmlTree.DIV(cellStyle, c.isValid() ? c : HtmlTree.EMPTY); if (rowStyle != null) { cell.addStyle(rowStyle); } @@ -386,7 +386,7 @@ public class Table extends Content { default -> throw new IllegalStateException(); }; - HtmlTree table = HtmlTree.DIV(tableStyle).addStyle(columnStyle); + var table = HtmlTree.DIV(tableStyle).addStyle(columnStyle); if ((tabMap == null || tabs.size() == 1) && !alwaysShowDefaultTab) { if (tabMap == null) { main.add(caption); @@ -396,7 +396,7 @@ public class Table extends Content { table.add(getTableBody()); main.add(table); } else { - HtmlTree tablist = HtmlTree.DIV(tabListStyle) + var tablist = HtmlTree.DIV(tabListStyle) .put(HtmlAttr.ROLE, "tablist") .put(HtmlAttr.ARIA_ORIENTATION, "horizontal"); @@ -413,7 +413,7 @@ public class Table extends Content { if (id == null) { throw new IllegalStateException("no id set for table"); } - HtmlTree tabpanel = new HtmlTree(TagName.DIV) + var tabpanel = new HtmlTree(TagName.DIV) .setId(HtmlIds.forTabPanel(id)) .put(HtmlAttr.ROLE, "tabpanel"); table.add(getTableBody()); @@ -425,7 +425,7 @@ public class Table extends Content { } private HtmlTree createTab(HtmlId tabId, HtmlStyle style, boolean defaultTab, Content tabLabel) { - HtmlTree tab = new HtmlTree(TagName.BUTTON) + var tab = new HtmlTree(TagName.BUTTON) .setId(tabId) .put(HtmlAttr.ROLE, "tab") .put(HtmlAttr.ARIA_SELECTED, defaultTab ? "true" : "false") diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java index 255f61a491b53e597f23b886141b8469013d7290..dca52e179b8904a9ff42ffd9039e3ecd7985be10 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.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 @@ -145,7 +145,7 @@ public class TableHeader extends Content { : (i == 0) ? HtmlStyle.colFirst : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast : (i == 1) ? HtmlStyle.colSecond : null; - HtmlTree cell = HtmlTree.DIV(HtmlStyle.tableHeader, cellContent); + var cell = HtmlTree.DIV(HtmlStyle.tableHeader, cellContent); if (style != null) { cell.addStyle(style); } 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 adf98e0b8a0942c10524aca5bc002f94716d55fb..70c451c1a3f5fe732f25c10d5c5a193369afbde5 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 @@ -202,8 +202,7 @@ public class TagletWriterImpl extends TagletWriter { @Override protected Content codeTagOutput(Element element, DocTree tag) { CommentHelper ch = utils.getCommentHelper(element); - Content result = HtmlTree.CODE(Text.of(utils.normalizeNewlines(ch.getText(tag)))); - return result; + return HtmlTree.CODE(Text.of(utils.normalizeNewlines(ch.getText(tag)))); } @Override @@ -223,7 +222,7 @@ public class TagletWriterImpl extends TagletWriter { } // ugly but simple; - // alternatives would be to walk the Content tree, or to add new functionality to Content + // alternatives would be to walk the Content's tree structure, or to add new functionality to Content private String extractText(Content c) { return c.toString().replaceAll("<[^>]+>", ""); } @@ -301,8 +300,8 @@ public class TagletWriterImpl extends TagletWriter { // define id attributes for state components so that generated descriptions may refer to them boolean defineID = (element.getKind() == ElementKind.RECORD) && !paramTag.isTypeParameter(); - Content nameTree = Text.of(paramName); - body.add(HtmlTree.CODE(defineID ? HtmlTree.SPAN_ID(HtmlIds.forParam(paramName), nameTree) : nameTree)); + Content nameContent = Text.of(paramName); + body.add(HtmlTree.CODE(defineID ? HtmlTree.SPAN_ID(HtmlIds.forParam(paramName), nameContent) : nameContent)); body.add(" - "); List description = ch.getDescription(paramTag); body.add(htmlWriter.commentTagsToContent(paramTag, element, description, context.within(paramTag))); @@ -353,7 +352,7 @@ public class TagletWriterImpl extends TagletWriter { // Use a different style if any link label is longer than 30 chars or contains commas. boolean hasLongLabels = links.stream() .anyMatch(c -> c.charCount() > SEE_TAG_MAX_INLINE_LENGTH || c.toString().contains(",")); - HtmlTree seeList = HtmlTree.UL(hasLongLabels ? HtmlStyle.seeListLong : HtmlStyle.seeList); + var seeList = HtmlTree.UL(hasLongLabels ? HtmlStyle.seeListLong : HtmlStyle.seeList); links.stream().filter(Content::isValid).forEach(item -> { seeList.add(HtmlTree.LI(item)); }); @@ -384,11 +383,11 @@ public class TagletWriterImpl extends TagletWriter { @Override protected Content snippetTagOutput(Element element, SnippetTree tag, StyledText content, String id, String lang) { - HtmlTree pre = new HtmlTree(TagName.PRE).setStyle(HtmlStyle.snippet); + var pre = new HtmlTree(TagName.PRE).setStyle(HtmlStyle.snippet); if (id != null && !id.isBlank()) { pre.put(HtmlAttr.ID, id); } - HtmlTree code = new HtmlTree(TagName.CODE) + var code = new HtmlTree(TagName.CODE) .add(HtmlTree.EMPTY); // Make sure the element is always rendered if (lang != null && !lang.isBlank()) { code.addStyle("language-" + lang); @@ -458,7 +457,7 @@ public class TagletWriterImpl extends TagletWriter { }); String copyText = resources.getText("doclet.Copy_snippet_to_clipboard"); String copiedText = resources.getText("doclet.Copied_snippet_to_clipboard"); - HtmlTree snippetContainer = HtmlTree.DIV(HtmlStyle.snippetContainer, + var snippetContainer = HtmlTree.DIV(HtmlStyle.snippetContainer, new HtmlTree(TagName.BUTTON) .add(HtmlTree.SPAN(Text.of(copyText)) .put(HtmlAttr.DATA_COPIED, copiedText)) @@ -525,15 +524,13 @@ public class TagletWriterImpl extends TagletWriter { body.add(" - "); body.add(desc); } - HtmlTree result = HtmlTree.DD(body); - return result; + return HtmlTree.DD(body); } @Override public Content throwsTagOutput(TypeMirror throwsType) { - HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink( + return HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink( new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER, throwsType)))); - return result; } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java index 57b2b470dee83178bf8c72435fb4233c253f3727..2b47dc8916fc1a018fa80313acd8b7ffe644a270 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java @@ -101,11 +101,11 @@ public class TreeWriter extends AbstractTreeWriter { * @throws DocFileIOException if there is a problem generating the overview tree page */ public void generateTreeFile() throws DocFileIOException { - HtmlTree body = getTreeHeader(); + HtmlTree body = getBody(); Content headContent = contents.hierarchyForAllPackages; - Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, + var heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, headContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); + var div = HtmlTree.DIV(HtmlStyle.header, heading); addPackageTreeLinks(div); Content mainContent = new ContentBuilder(); mainContent.add(div); @@ -122,18 +122,18 @@ public class TreeWriter extends AbstractTreeWriter { /** * Add the links to all the package tree files. * - * @param contentTree the content tree to which the links will be added + * @param content the content to which the links will be added */ - protected void addPackageTreeLinks(Content contentTree) { + protected void addPackageTreeLinks(Content content) { //Do nothing if only unnamed package is used if (isUnnamedPackage()) { return; } if (!classesOnly) { - Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, + var span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, contents.packageHierarchies); - contentTree.add(span); - HtmlTree ul = HtmlTree.UL(HtmlStyle.horizontal); + content.add(span); + var ul = HtmlTree.UL(HtmlStyle.horizontal); int i = 0; for (PackageElement pkg : packages) { // If the package name length is 0 or if -nodeprecated option @@ -145,7 +145,7 @@ public class TreeWriter extends AbstractTreeWriter { continue; } DocPath link = pathString(pkg, DocPaths.PACKAGE_TREE); - Content li = HtmlTree.LI(links.createLink(link, + var li = HtmlTree.LI(links.createLink(link, getLocalizedPackageName(pkg))); if (i < packages.size() - 1) { li.add(", "); @@ -153,16 +153,14 @@ public class TreeWriter extends AbstractTreeWriter { ul.add(li); i++; } - contentTree.add(ul); + content.add(ul); } } /** - * Get the tree header. - * - * @return a content tree for the tree header + * {@return a new HTML BODY element} */ - protected HtmlTree getTreeHeader() { + private HtmlTree getBody() { String title = resources.getText("doclet.Window_Class_Hierarchy"); HtmlTree bodyTree = getBody(getWindowTitle(title)); bodyContents.setHeader(getHeader(PageMode.TREE)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/BodyContents.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/BodyContents.java index 33ebbc43b2d2c2bef4ef0c92ae13c81a62abcb68..75242fc5b900a63d05bdbddc432418c8462692d1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/BodyContents.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/BodyContents.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 @@ -94,7 +94,7 @@ public class BodyContents extends Content { HtmlTree flexHeader = header.addStyle(HtmlStyle.flexHeader); - HtmlTree flexContent = HtmlTree.DIV(HtmlStyle.flexContent) + var flexContent = HtmlTree.DIV(HtmlStyle.flexContent) .add(HtmlTree.MAIN().add(mainContents)) .add(footer == null ? HtmlTree.EMPTY : footer); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java index 79d398f9c9ee39a8977306aec9dea85f9221e582..06112b09e90023d1bc6098cf4594400209b7526e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.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 @@ -28,7 +28,6 @@ package jdk.javadoc.internal.doclets.formats.html.markup; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -38,7 +37,7 @@ import jdk.javadoc.internal.doclets.toolkit.Content; * A sequence of Content nodes. */ public class ContentBuilder extends Content { - protected List contents = Collections.emptyList(); + protected List contents = List.of(); public ContentBuilder() { } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index adbd5ef09fd3b257b77087fbcb2032592e022a5d..015a4806acabd5e78a59d1a6eed8b47b808234f5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.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 @@ -31,7 +31,6 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; @@ -61,12 +60,12 @@ public class Head extends Content { private String generator; private boolean showTimestamp; private DocPath mainStylesheet; - private List additionalStylesheets = Collections.emptyList(); + private List additionalStylesheets = List.of(); private boolean index; private Script mainBodyScript; private final List + """, """ """, @@ -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/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java index 4b0dd06a2a246adc35c34432829beaf02cea552f..9923a191a57b18e2566696b3a873d252cd6cf12e 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.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 @@ -1079,11 +1079,11 @@ public class TestSnippetTag extends SnippetTester { checkExit(Exit.ERROR); checkOutput(Output.OUT, true, """ - A.java:4: error: File not found: %s""".formatted(fileName)); + A.java:4: error: file not found on source path or snippet path: %s""".formatted(fileName)); checkOutput("pkg/A.html", true, """
    invalid @snippet -
    File not found: text.txt
    +
    file not found on source path or snippet path: text.txt
    """); checkNoCrashes(); @@ -1140,7 +1140,7 @@ public class TestSnippetTag extends SnippetTester { checkExit(Exit.ERROR); checkOutput(Output.OUT, true, """ - A.java:4: error: File not found: %s""".formatted(fileName)); + A.java:4: error: file not found on source path or snippet path: %s""".formatted(fileName)); checkNoCrashes(); } @@ -1869,7 +1869,7 @@ public class TestSnippetTag extends SnippetTester { checkExit(Exit.ERROR); checkOutput(Output.OUT, true, """ - A.java:4: error: File not found: %s""".formatted(fileName)); + A.java:4: error: file not found on source path or snippet path: %s""".formatted(fileName)); checkNoCrashes(); } 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/HighlightUITest.java b/test/langtools/jdk/jshell/HighlightUITest.java new file mode 100644 index 0000000000000000000000000000000000000000..ede22e8f0107950f95afeb3ff0ce49a125b19666 --- /dev/null +++ b/test/langtools/jdk/jshell/HighlightUITest.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. + */ + +/** + * @test + * @bug 8274148 + * @summary Check the UI behavior of snippet highligting + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jshell/jdk.internal.jshell.tool:open + * jdk.jshell/jdk.internal.jshell.tool.resources:open + * jdk.jshell/jdk.jshell:open + * @library /tools/lib + * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask + * @build Compiler UITesting + * @compile HighlightUITest.java + * @run testng HighlightUITest + */ + +import org.testng.annotations.Test; + +@Test +public class HighlightUITest extends UITesting { + + public HighlightUITest() { + super(true); + } + + public void testHighlight() throws Exception { + System.setProperty("test.enable.highlighter", "true"); + doRunTest((inputSink, out) -> { + inputSink.write("var s = new String(byte[0], 0);"); + waitOutput(out, "var s = new String\\(byte\\[0]\u001B\\[3D\u001B\\[3C, 0\\)\u001B\\[12D\u001B\\[12C;\r" + + "\u001B\\[4mvar\u001B\\[0m \u001B\\[1ms\u001B\\[0m = \u001B\\[4mnew\u001B\\[0m String\\(\u001B\\[4mbyte\u001B\\[0m\\u001B\\[8C"); + }); + } + +} \ No newline at end of file diff --git a/test/langtools/jdk/jshell/SnippetHighlightTest.java b/test/langtools/jdk/jshell/SnippetHighlightTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4a34e8820d50ad5e078b4fb98f9cd9abc8191c31 --- /dev/null +++ b/test/langtools/jdk/jshell/SnippetHighlightTest.java @@ -0,0 +1,117 @@ +/* + * 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 8274148 + * @summary Check snippet highlighting + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * jdk.jshell/jdk.jshell:open + * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask + * @build KullaTesting TestingInputStream Compiler + * @run testng SnippetHighlightTest + */ + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.testng.annotations.Test; + +import jdk.jshell.SourceCodeAnalysis.Highlight; + +import static org.testng.Assert.*; + +@Test +public class SnippetHighlightTest extends KullaTesting { + + public void testMemberExpr() { + assertEval("@Deprecated class TestClass { }"); + assertEval("class TestConstructor { @Deprecated TestConstructor() {} }"); + assertEval("class TestMethod { @Deprecated void test() {} }"); + assertHighlights("TestClass t", "Highlight[start=0, end=9, attributes=[DEPRECATED]]", + "Highlight[start=10, end=11, attributes=[DECLARATION]]"); + assertHighlights("TestClass.class", "Highlight[start=0, end=9, attributes=[DEPRECATED]]", + "Highlight[start=10, end=15, attributes=[KEYWORD]]"); + assertHighlights("new TestConstructor()", "Highlight[start=0, end=3, attributes=[KEYWORD]]", + "Highlight[start=4, end=19, attributes=[DEPRECATED]]"); + assertHighlights("new TestMethod().test()", "Highlight[start=0, end=3, attributes=[KEYWORD]]", + "Highlight[start=17, end=21, attributes=[DEPRECATED]]"); + assertHighlights("var v = 0;", "Highlight[start=0, end=3, attributes=[KEYWORD]]", + "Highlight[start=4, end=5, attributes=[DECLARATION]]"); + assertHighlights("int i = switch (0) { case 0: yield 0;};", + "Highlight[start=0, end=3, attributes=[KEYWORD]]", + "Highlight[start=4, end=5, attributes=[DECLARATION]]", + "Highlight[start=8, end=14, attributes=[KEYWORD]]", + "Highlight[start=21, end=25, attributes=[KEYWORD]]", + "Highlight[start=29, end=34, attributes=[KEYWORD]]"); + assertHighlights("sealed class C permits A {}", + "Highlight[start=0, end=6, attributes=[KEYWORD]]", + "Highlight[start=7, end=12, attributes=[KEYWORD]]", + "Highlight[start=13, end=14, attributes=[DECLARATION]]", + "Highlight[start=15, end=22, attributes=[KEYWORD]]"); + assertHighlights("non-sealed class C extends A {}", + "Highlight[start=0, end=10, attributes=[KEYWORD]]", + "Highlight[start=11, end=16, attributes=[KEYWORD]]", + "Highlight[start=17, end=18, attributes=[DECLARATION]]", + "Highlight[start=19, end=26, attributes=[KEYWORD]]"); + assertHighlights("interface I {}", + "Highlight[start=0, end=9, attributes=[KEYWORD]]", + "Highlight[start=10, end=11, attributes=[DECLARATION]]"); + assertHighlights("@interface I {}", + "Highlight[start=1, end=10, attributes=[KEYWORD]]", + "Highlight[start=11, end=12, attributes=[DECLARATION]]"); + assertHighlights("enum E {A, B;}", + "Highlight[start=0, end=4, attributes=[KEYWORD]]", + "Highlight[start=5, end=6, attributes=[DECLARATION]]", + "Highlight[start=8, end=9, attributes=[DECLARATION]]", + "Highlight[start=11, end=12, attributes=[DECLARATION]]"); + assertHighlights("record R(int i) {}", + "Highlight[start=0, end=6, attributes=[KEYWORD]]", + "Highlight[start=7, end=8, attributes=[DECLARATION]]", + "Highlight[start=9, end=12, attributes=[KEYWORD]]", + "Highlight[start=13, end=14, attributes=[DECLARATION]]"); + assertHighlights("void method() {}", + "Highlight[start=0, end=4, attributes=[KEYWORD]]", + "Highlight[start=5, end=11, attributes=[DECLARATION]]"); + } + + private void assertHighlights(String code, String... expected) { + List completions = computeHighlights(code); + assertEquals(completions, Arrays.asList(expected), "Input: " + code + ", " + completions.toString()); + } + + private List computeHighlights(String code) { + waitIndexingFinished(); + + List highlights = + getAnalysis().highlights(code); + return highlights.stream() + .map(h -> h.toString()) + .distinct() + .collect(Collectors.toList()); + } +} 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/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index 9f9f8f780144708d7f61108f4708b10c79cd457e..afceccad6335dff0148078647c44ce70de3aa3cf 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -57,7 +57,6 @@ compiler.misc.bad.runtime.invisible.param.annotations # bad class file compiler.misc.bad.signature # bad class file compiler.misc.bad.requires.flag # bad class file compiler.misc.bad.type.annotation.value -compiler.misc.base.membership # UNUSED compiler.misc.class.file.not.found # ClassReader compiler.misc.class.file.wrong.class compiler.misc.exception.message # uncommon completion failure based on a string 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 a052f087af6047b9b71d1583b9b1768edf3205b8..08b0ce5002b94f717a58e4998b02185ae518d3bf 100644 --- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.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 @@ -56,7 +56,7 @@ import toolbox.JavaTask; import toolbox.JavacTask; import toolbox.Task; import toolbox.TestRunner; -import toolbox.TestRunner; +import toolbox.TestRunner.Test; import toolbox.ToolBox; public class SourceLauncherTest extends TestRunner { @@ -231,6 +231,7 @@ public class SourceLauncherTest extends TestRunner { "error: cannot use source-code launcher with a security manager enabled"); } + @Test public void testSystemProperty(Path base) throws IOException { tb.writeJavaFiles(base, "class ShowProperty {\n" + 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/sealed/ValidateJarWithSealedAndRecord.java b/test/langtools/tools/javac/sealed/ValidateJarWithSealedAndRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..c133b87a1cd411756faec29598dc4a7c50560719 --- /dev/null +++ b/test/langtools/tools/javac/sealed/ValidateJarWithSealedAndRecord.java @@ -0,0 +1,72 @@ +/* + * 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 8282446 8282508 + * @summary Jar validation fails when sealed classes and records are involved + * @run main ValidateJarWithSealedAndRecord + */ + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.spi.ToolProvider; + +public class ValidateJarWithSealedAndRecord { + + public static void main(String args[]) throws Exception { + ValidateJarWithSealedAndRecord theTest = new ValidateJarWithSealedAndRecord(); + theTest.run(); + } + + void run() throws Exception { + generateFilesNeeded(); + } + + void writeFile(String f, String contents) throws IOException { + PrintStream s = new PrintStream(new FileOutputStream(f)); + s.println(contents); + s.close(); + } + + void generateFilesNeeded() throws Exception { + ToolProvider jarTool = ToolProvider.findFirst("jar").orElseThrow(() -> new RuntimeException("jar tool not found")); + writeFile("Foo.java", + """ + public sealed interface Foo { + record Bar() implements Foo {} + } + """ + ); + com.sun.tools.javac.Main.compile(new String[]{"-d", "out", "Foo.java"}); + jarTool.run(System.out, System.err, new String[] {"--create", "--file", "foo.jar", "-C", "out", "."}); + /* we need to create a fresh instance with clean options in other case the tool will + * keep a copy of the options we just passed above + */ + jarTool = ToolProvider.findFirst("jar").orElseThrow(() -> new RuntimeException("jar tool not found")); + if (jarTool.run(System.out, System.err, new String[]{"--validate", "--file", "foo.jar"}) != 0) { + throw new AssertionError("jar file couldn't be validated"); + } + } +} 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/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java index 3ca1de653a4f7e25112833d39ea693b08d59ea43..219d3797453dfbb3c538a937b22d3197d95ccd6d 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java @@ -45,7 +45,7 @@ import java.util.Set; */ public class TestMutuallyExclusivePlatformPredicates { private static enum MethodGroup { - ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isX64", "isX86"), + ARCH("isAArch64", "isARM", "isRISCV64", "isPPC", "isS390x", "isX64", "isX86"), BITNESS("is32bit", "is64bit"), OS("isAix", "isLinux", "isOSX", "isWindows"), VM_TYPE("isClient", "isServer", "isMinimal", "isZero", "isEmbedded"), diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index a8405c937226a178dabc5c60cd4a3e53ff427430..3084634018bd3cf2724247347a58a2740549e7d1 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -197,6 +197,10 @@ public class Platform { return isArch("arm.*"); } + public static boolean isRISCV64() { + return isArch("riscv64"); + } + public static boolean isPPC() { return isArch("ppc.*"); } 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/StringBuilderToString.java b/test/micro/org/openjdk/bench/java/lang/StringBuilderToString.java new file mode 100644 index 0000000000000000000000000000000000000000..b38410204f348892fb652c26fc9d3def1a3aec58 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringBuilderToString.java @@ -0,0 +1,60 @@ +/* + * 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.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.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Fork(3) +public class StringBuilderToString { + @Param({"128", "256", "1024"}) + public int MIXED_SIZE; + + /** + * This microbench simulates how java.io.BufferedReader uses StringBuilder. + */ + @Benchmark + public String toStringWithMixedChars() { + StringBuilder sb = new StringBuilder(MIXED_SIZE); + for (int i = 0; i < MIXED_SIZE - 4; ++i) { + sb.append('a'); + } + sb.append('\u3042'); // can't be encoded in latin-1, + return sb.toString(); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/StringDecode.java b/test/micro/org/openjdk/bench/java/lang/StringDecode.java index c5609ce4e51fd14406f613d53b4f25105fcb806f..ee4f8df7c734f21eb235f1c380843c66ae5dde42 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringDecode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringDecode.java @@ -87,7 +87,7 @@ public class StringDecode { 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, 512 + 7, charset)); + bh.consume(new String(longAsciiString, 512, 7, charset)); } @Benchmark @@ -103,7 +103,7 @@ public class StringDecode { 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, 512 + 7, charset)); + bh.consume(new String(longLatin1OnlyString, 512, 7, charset)); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.java b/test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.java index cf0eed32e07c1c988e92093db90bd9f743761ff6..8381673028ef9a72f09a7b04ea499d4f461010da 100644 --- a/test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.java +++ b/test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.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 @@ -26,53 +26,97 @@ package org.openjdk.bench.java.math; import java.util.Random; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Thread) public class FpRoundingBenchmark { - @Param({"1024"}) + @Param({"1024", "2048"}) public int TESTSIZE; public double[] DargV1; - - public double[] Res; + public double[] ResD; + public long[] ResL; + public float[] FargV1; + public float[] ResF; + public int[] ResI; public final double[] DspecialVals = { - 0.0, -0.0, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY}; + 0.0, -0.0, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, + Double.MAX_VALUE, -Double.MAX_VALUE, Double.MIN_VALUE, -Double.MIN_VALUE, + Double.MIN_NORMAL + }; + + public final float[] FspecialVals = { + 0.0f, -0.0f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, + Float.MAX_VALUE, -Float.MAX_VALUE, Float.MIN_VALUE, -Float.MIN_VALUE, + Float.MIN_NORMAL + }; @Setup(Level.Trial) public void BmSetup() { - int i = 0; - Random r = new Random(1024); - DargV1 = new double[TESTSIZE]; - Res = new double[TESTSIZE]; - - for (; i < DspecialVals.length; i++) { - DargV1[i] = DspecialVals[i]; - } - - for (; i < TESTSIZE; i++) { - DargV1[i] = r.nextDouble()*TESTSIZE; - } + int i = 0; + Random r = new Random(1024); + + DargV1 = new double[TESTSIZE]; + ResD = new double[TESTSIZE]; + + for (; i < DspecialVals.length; i++) { + DargV1[i] = DspecialVals[i]; + } + + for (; i < TESTSIZE; i++) { + DargV1[i] = Double.longBitsToDouble(r.nextLong());; + } + + FargV1 = new float[TESTSIZE]; + ResF = new float[TESTSIZE]; + + i = 0; + for (; i < FspecialVals.length; i++) { + FargV1[i] = FspecialVals[i]; + } + + for (; i < TESTSIZE; i++) { + FargV1[i] = Float.intBitsToFloat(r.nextInt()); + } + + ResI = new int[TESTSIZE]; + ResL = new long[TESTSIZE]; + } + + @Benchmark + public void test_ceil() { + for (int i = 0; i < TESTSIZE; i++) { + ResD[i] = Math.ceil(DargV1[i]); + } + } + + @Benchmark + public void test_floor() { + for (int i = 0; i < TESTSIZE; i++) { + ResD[i] = Math.floor(DargV1[i]); + } } @Benchmark - public void testceil(Blackhole bh) { - for (int i = 0; i < TESTSIZE; i++) - Res[i] = Math.ceil(DargV1[i]); + public void test_rint() { + for (int i = 0; i < TESTSIZE; i++) { + ResD[i] = Math.rint(DargV1[i]); + } } @Benchmark - public void testfloor(Blackhole bh) { - for (int i = 0; i < TESTSIZE; i++) - Res[i] = Math.floor(DargV1[i]); + public void test_round_double() { + for (int i = 0; i < TESTSIZE; i++) { + ResL[i] = Math.round(DargV1[i]); + } } @Benchmark - public void testrint(Blackhole bh) { - for (int i = 0; i < TESTSIZE; i++) - Res[i] = Math.rint(DargV1[i]); + public void test_round_float() { + for (int i = 0; i < TESTSIZE; i++) { + ResI[i] = Math.round(FargV1[i]); + } } } diff --git a/test/micro/org/openjdk/bench/java/time/GetYearBench.java b/test/micro/org/openjdk/bench/java/time/GetYearBench.java new file mode 100644 index 0000000000000000000000000000000000000000..59d3b84a29793e4b273842925d9d1851d0dbb309 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/time/GetYearBench.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 org.openjdk.bench.java.time; + +import java.time.Duration; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +import java.util.Locale; +import java.util.Random; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +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.infra.Blackhole; + +/** + * Examine ability to perform escape analysis on expressions + * such as {@code Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC).getYear()} + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) +@Fork(3) +@State(Scope.Benchmark) +public class GetYearBench { + + private TimeZone UTC = TimeZone.getTimeZone("UTC"); + + private TimeZone LONDON = TimeZone.getTimeZone("Europe/London"); + + private long[] INSTANT_MILLIS; + + private int[] YEARS; + + @Setup + public void createInstants() { + // Various instants during the same day + final Instant loInstant = Instant.EPOCH.plus(Duration.ofDays(365*50)); // 2020-01-01 + final Instant hiInstant = loInstant.plus(Duration.ofDays(1)); + final long maxOffsetNanos = Duration.between(loInstant, hiInstant).toNanos(); + final Random random = new Random(0); + INSTANT_MILLIS = IntStream + .range(0, 1_000) + .mapToObj(ignored -> { + final long offsetNanos = (long) Math.floor(random.nextDouble() * maxOffsetNanos); + return loInstant.plus(offsetNanos, ChronoUnit.NANOS); + }) + .mapToLong(instant -> instant.toEpochMilli()) + .toArray(); + YEARS = new int[INSTANT_MILLIS.length]; + } + + @Benchmark + public int[] getYearFromMillisZoneOffset() { + for (int i = 0; i < YEARS.length; i++) { + YEARS[i] = Instant.ofEpochMilli(INSTANT_MILLIS[i]).atZone(ZoneOffset.UTC).getYear(); + } + return YEARS; + } + + @Benchmark + public int[] getYearFromMillisZoneRegionUTC() { + for (int i = 0; i < YEARS.length; i++) { + YEARS[i] = Instant.ofEpochMilli(INSTANT_MILLIS[i]).atZone(UTC.toZoneId()).getYear(); + } + return YEARS; + } + + @Benchmark + public int[] getYearFromMillisZoneRegion() { + for (int i = 0; i < YEARS.length; i++) { + YEARS[i] = Instant.ofEpochMilli(INSTANT_MILLIS[i]).atZone(LONDON.toZoneId()).getYear(); + } + return YEARS; + } + + @Benchmark + public int[] getYearFromMillisZoneRegionNormalized() { + for (int i = 0; i < YEARS.length; i++) { + YEARS[i] = Instant.ofEpochMilli(INSTANT_MILLIS[i]).atZone(UTC.toZoneId().normalized()).getYear(); + } + return YEARS; + } +} 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/MaxMinOptimizeTest.java b/test/micro/org/openjdk/bench/vm/compiler/MaxMinOptimizeTest.java index db75b94db33f69a00b7376ca9ca9556bed07b4df..ec83488464a450bdd327b1314651ee4f7226a2f8 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/MaxMinOptimizeTest.java +++ b/test/micro/org/openjdk/bench/vm/compiler/MaxMinOptimizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it 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]; + } + } + } +}