diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml index 4db164f1a73..0a719f8fa37 100644 --- a/.github/workflows/submit.yml +++ b/.github/workflows/submit.yml @@ -9,7 +9,7 @@ on: platforms: description: "Platform(s) to execute on" required: true - default: "Linux x64, Windows x64, macOS x64" + default: "Linux x64, Linux x86, Windows x64, macOS x64" jobs: prerequisites: @@ -18,7 +18,7 @@ jobs: outputs: should_run: ${{ steps.check_submit.outputs.should_run }} bundle_id: ${{ steps.check_bundle_id.outputs.bundle_id }} - platform_linux_x32: ${{ steps.check_platforms.outputs.platform_linux_x32 }} + platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }} platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }} platform_windows_x64: ${{ steps.check_platforms.outputs.platform_windows_x64 }} platform_macos_x64: ${{ steps.check_platforms.outputs.platform_macos_x64 }} @@ -33,12 +33,13 @@ jobs: id: check_platforms run: | echo "::set-output name=platform_linux_x64::${{ contains(github.event.inputs.platforms, 'linux x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x64'))) }}" - echo "::set-output name=platform_linux_x32::${{ contains(github.event.inputs.platforms, 'linux x32') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x32'))) }}" + echo "::set-output name=platform_linux_x86::${{ contains(github.event.inputs.platforms, 'linux x86') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x86'))) }}" echo "::set-output name=platform_windows_x64::${{ contains(github.event.inputs.platforms, 'windows x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'windows x64'))) }}" echo "::set-output name=platform_macos_x64::${{ contains(github.event.inputs.platforms, 'macos x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos x64'))) }}" if: steps.check_submit.outputs.should_run != 'false' - name: Determine unique bundle identifier + id: check_bundle_id run: echo "::set-output name=bundle_id::${GITHUB_ACTOR}_${GITHUB_SHA:0:8}" if: steps.check_submit.outputs.should_run != 'false' @@ -350,24 +351,52 @@ jobs: if: always() run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV - - name: Persist test logs + - name: Package test results + if: always() + working-directory: build/run-test-prebuilt/test-results/ + run: > + zip -r9 + "$HOME/linux-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" + . + continue-on-error: true + + - name: Package test support + if: always() + working-directory: build/run-test-prebuilt/test-support/ + run: > + zip -r9 + "$HOME/linux-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" + . + -i *.jtr + -i hs_err* + -i replay* + continue-on-error: true + + - name: Persist test results + if: always() + uses: actions/upload-artifact@v2 + with: + path: ~/linux-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip + continue-on-error: true + + - name: Persist test outputs if: always() uses: actions/upload-artifact@v2 with: - name: linux-x64${{ matrix.artifact }}_testlogs_${{ env.logsuffix }} - path: build/*/test-results + path: ~/linux-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true - linux_x32_build: - name: Linux x32 + linux_x86_build: + name: Linux x86 runs-on: "ubuntu-latest" needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_x32 != 'false' + if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_x86 != 'false' strategy: fail-fast: false matrix: flavor: + - build release - build debug include: - flavor: build debug @@ -438,7 +467,7 @@ jobs: - name: Configure run: > bash configure - --with-conf-name=linux-x32 + --with-conf-name=linux-x86 --with-target-bits=32 ${{ matrix.flags }} --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} @@ -452,9 +481,198 @@ jobs: working-directory: jdk - name: Build - run: make CONF_NAME=linux-x32 ${{ matrix.build-target }} + run: make CONF_NAME=linux-x86 ${{ matrix.build-target }} working-directory: jdk + - name: Persist test bundles + uses: actions/upload-artifact@v2 + with: + name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} + path: | + jdk/build/linux-x86/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}.tar.gz + jdk/build/linux-x86/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}.tar.gz + if: matrix.build-target == false + + linux_x86_test: + name: Linux x86 + runs-on: "ubuntu-latest" + needs: + - prerequisites + - linux_x86_build + + strategy: + fail-fast: false + matrix: + test: + - jdk/tier1 part 1 + - jdk/tier1 part 2 + - jdk/tier1 part 3 + - langtools/tier1 + - hs/tier1 common + - hs/tier1 compiler + - hs/tier1 gc + - hs/tier1 runtime + - hs/tier1 serviceability + include: + - test: jdk/tier1 part 1 + suites: test/jdk/:tier1_part1 + - test: jdk/tier1 part 2 + suites: test/jdk/:tier1_part2 + - test: jdk/tier1 part 3 + suites: test/jdk/:tier1_part3 + - test: langtools/tier1 + suites: test/langtools/:tier1 + - test: hs/tier1 common + suites: test/hotspot/jtreg/:tier1_common + artifact: -debug + - test: hs/tier1 compiler + suites: test/hotspot/jtreg/:tier1_compiler + artifact: -debug + - test: hs/tier1 gc + suites: test/hotspot/jtreg/:tier1_gc + artifact: -debug + - test: hs/tier1 runtime + suites: test/hotspot/jtreg/:tier1_runtime + artifact: -debug + - test: hs/tier1 serviceability + suites: test/hotspot/jtreg/:tier1_serviceability + artifact: -debug + + # Reduced 32-bit build uses the same boot JDK as 64-bit build + env: + JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + 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 }}" + BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" + + steps: + - name: Checkout the source + uses: actions/checkout@v2 + + - name: Restore boot JDK from cache + id: bootjdk + uses: actions/cache@v2 + with: + path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} + key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 + + - name: Download boot JDK + run: | + mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" + wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" + echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - + tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" + mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" + if: steps.bootjdk.outputs.cache-hit != 'true' + + - name: Restore jtreg artifact + id: jtreg_restore + uses: actions/download-artifact@v2 + with: + name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} + path: ~/jtreg/ + continue-on-error: true + + - name: Restore jtreg artifact (retry) + uses: actions/download-artifact@v2 + with: + name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} + path: ~/jtreg/ + if: steps.jtreg_restore.outcome == 'failure' + + - name: Restore build artifacts + id: build_restore + uses: actions/download-artifact@v2 + with: + name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} + path: ~/jdk-linux-x86${{ matrix.artifact }} + continue-on-error: true + + - name: Restore build artifacts (retry) + uses: actions/download-artifact@v2 + with: + name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} + path: ~/jdk-linux-x86${{ matrix.artifact }} + if: steps.build_restore.outcome == 'failure' + + - name: Unpack jdk + run: | + mkdir -p "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}" + tar -xf "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}" + + - name: Unpack tests + run: | + mkdir -p "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}" + tar -xf "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}" + + - name: Find root of jdk image dir + run: | + imageroot=`find ${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }} -name release -type f` + echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV + + - name: Run tests + run: > + JDK_IMAGE_DIR=${{ env.imageroot }} + TEST_IMAGE_DIR=${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }} + BOOT_JDK=${HOME}/bootjdk/${BOOT_JDK_VERSION} + JT_HOME=${HOME}/jtreg + make test-prebuilt + CONF_NAME=run-test-prebuilt + LOG_CMDLINES=true + JTREG_VERBOSE=fail,error,time + TEST="${{ matrix.suites }}" + TEST_OPTS_JAVA_OPTIONS= + JTREG_KEYWORDS="!headful" + JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" + + - name: Check that all tests executed successfully + if: always() + run: > + if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then + cat build/*/test-results/*/text/newfailures.txt ; + exit 1 ; + fi + + - name: Create suitable test log artifact name + if: always() + run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV + + - name: Package test results + if: always() + working-directory: build/run-test-prebuilt/test-results/ + run: > + zip -r9 + "$HOME/linux-x86${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" + . + continue-on-error: true + + - name: Package test support + if: always() + working-directory: build/run-test-prebuilt/test-support/ + run: > + zip -r9 + "$HOME/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" + . + -i *.jtr + -i hs_err* + -i replay* + continue-on-error: true + + - name: Persist test results + if: always() + uses: actions/upload-artifact@v2 + with: + path: ~/linux-x86${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip + continue-on-error: true + + - name: Persist test outputs + if: always() + uses: actions/upload-artifact@v2 + with: + path: ~/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip + continue-on-error: true + windows_x64_build: name: Windows x64 runs-on: "windows-latest" @@ -734,12 +952,41 @@ jobs: if: always() run: echo ("logsuffix=" + ("${{ matrix.test }}" -replace "/", "_" -replace " ", "_")) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 - - name: Persist test logs + - name: Package test results + if: always() + working-directory: build/run-test-prebuilt/test-results/ + run: > + $env:Path = "$HOME\cygwin\cygwin64\bin;$env:Path" ; + zip -r9 + "$HOME/windows-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" + . + continue-on-error: true + + - name: Package test support + if: always() + working-directory: build/run-test-prebuilt/test-support/ + run: > + $env:Path = "$HOME\cygwin\cygwin64\bin;$env:Path" ; + zip -r9 + "$HOME/windows-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" + . + -i *.jtr + -i hs_err* + -i replay* + continue-on-error: true + + - name: Persist test results + if: always() + uses: actions/upload-artifact@v2 + with: + path: ~/windows-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip + continue-on-error: true + + - name: Persist test outputs if: always() uses: actions/upload-artifact@v2 with: - name: windows-x64${{ matrix.artifact }}_testlogs_${{ env.logsuffix }} - path: build/*/test-results + path: ~/windows-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true macos_x64_build: @@ -989,12 +1236,39 @@ jobs: if: always() run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV - - name: Persist test logs + - name: Package test results + if: always() + working-directory: build/run-test-prebuilt/test-results/ + run: > + zip -r9 + "$HOME/macos-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" + . + continue-on-error: true + + - name: Package test support + if: always() + working-directory: build/run-test-prebuilt/test-support/ + run: > + zip -r9 + "$HOME/macos-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" + . + -i *.jtr + -i hs_err* + -i replay* + continue-on-error: true + + - name: Persist test results if: always() uses: actions/upload-artifact@v2 with: - name: macos-x64${{ matrix.artifact }}_testlogs_${{ env.logsuffix }} - path: build/*/test-results + path: ~/macos-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip + continue-on-error: true + + - name: Persist test outputs + if: always() + uses: actions/upload-artifact@v2 + with: + path: ~/macos-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true artifacts: @@ -1003,7 +1277,9 @@ jobs: if: always() continue-on-error: true needs: + - prerequisites - linux_x64_test + - linux_x86_test - windows_x64_test - macos_x64_test diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 339d9f0ac5f..63dc9a5767d 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -759,7 +759,6 @@ TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@ # Build setup ENABLE_AOT:=@ENABLE_AOT@ -ENABLE_INTREE_EC:=@ENABLE_INTREE_EC@ USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@ USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@ USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@ diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION index 1b183ac504b..f5b7dba32a4 100644 --- a/make/data/tzdata/VERSION +++ b/make/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2020b +tzdata2020c diff --git a/make/data/tzdata/australasia b/make/data/tzdata/australasia index 0c8008b1259..1f0fd47959f 100644 --- a/make/data/tzdata/australasia +++ b/make/data/tzdata/australasia @@ -404,6 +404,19 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 # From Michael Deckers (2019-08-06): # https://www.laws.gov.fj/LawsAsMade/downloadfile/848 +# From Raymond Kumar (2020-10-08): +# [DST in Fiji] is from December 20th 2020, till 17th January 2021. +# From Alan Mintz (2020-10-08): +# https://www.laws.gov.fj/LawsAsMade/GetFile/1071 +# From Tim Parenti (2020-10-08): +# https://www.fijivillage.com/news/Daylight-saving-from-Dec-20th-this-year-to-Jan-17th-2021-8rf4x5/ +# "Minister for Employment, Parveen Bala says they had never thought of +# stopping daylight saving. He says it was just to decide on when it should +# start and end. Bala says it is a short period..." +# Since the end date is still in line with our ongoing predictions, assume for +# now that the later-than-usual start date is a one-time departure from the +# recent second Sunday in November pattern. + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 - Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - @@ -415,7 +428,9 @@ Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 - Rule Fiji 2014 only - Jan Sun>=18 2:00 0 - Rule Fiji 2014 2018 - Nov Sun>=1 2:00 1:00 - Rule Fiji 2015 max - Jan Sun>=12 3:00 0 - -Rule Fiji 2019 max - Nov Sun>=8 2:00 1:00 - +Rule Fiji 2019 only - Nov Sun>=8 2:00 1:00 - +Rule Fiji 2020 only - Dec 20 2:00 1:00 - +Rule Fiji 2021 max - Nov Sun>=8 2:00 1:00 - # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva 12:00 Fiji +12/+13 diff --git a/make/data/tzdata/europe b/make/data/tzdata/europe index c556d2d482b..2b0c7be51c3 100644 --- a/make/data/tzdata/europe +++ b/make/data/tzdata/europe @@ -1612,6 +1612,8 @@ Rule Hungary 1946 only - Oct 7 2:00 0 - # https://library.hungaricana.hu/hu/view/Zala_1948_09/?pg=64 # https://library.hungaricana.hu/hu/view/SatoraljaujhelyiLeveltar_ZempleniNepujsag_1948/?pg=53 # https://library.hungaricana.hu/hu/view/SatoraljaujhelyiLeveltar_ZempleniNepujsag_1948/?pg=160 +# https://library.hungaricana.hu/hu/view/UjSzo_1949_01-04/?pg=102 +# https://library.hungaricana.hu/hu/view/KeletMagyarorszag_1949_03/?pg=96 # https://library.hungaricana.hu/hu/view/Delmagyarorszag_1949_09/?pg=94 Rule Hungary 1947 1949 - Apr Sun>=4 2:00s 1:00 S Rule Hungary 1947 1949 - Oct Sun>=1 2:00s 0 - @@ -1627,9 +1629,10 @@ Rule Hungary 1955 only - Oct 2 3:00 0 - # https://library.hungaricana.hu/hu/view/PestMegyeiHirlap_1957_09/?pg=143 Rule Hungary 1956 1957 - Jun Sun>=1 2:00 1:00 S Rule Hungary 1956 1957 - Sep lastSun 3:00 0 - -# https://library.hungaricana.hu/hu/view/DTT_KOZL_TanacsokKozlonye_1980/?pg=1227 +# https://library.hungaricana.hu/hu/view/DTT_KOZL_TanacsokKozlonye_1980/?pg=189 Rule Hungary 1980 only - Apr 6 0:00 1:00 S Rule Hungary 1980 only - Sep 28 1:00 0 - +# https://library.hungaricana.hu/hu/view/DTT_KOZL_TanacsokKozlonye_1980/?pg=1227 # https://library.hungaricana.hu/hu/view/Delmagyarorszag_1981_01/?pg=79 # https://library.hungaricana.hu/hu/view/DTT_KOZL_TanacsokKozlonye_1982/?pg=115 # https://library.hungaricana.hu/hu/view/DTT_KOZL_TanacsokKozlonye_1983/?pg=85 @@ -1640,6 +1643,7 @@ Rule Hungary 1981 1983 - Sep lastSun 1:00 0 - Zone Europe/Budapest 1:16:20 - LMT 1890 Nov 1 1:00 C-Eur CE%sT 1918 # https://library.hungaricana.hu/hu/view/OGYK_RT_1941/?pg=1204 +# https://library.hungaricana.hu/hu/view/OGYK_RT_1942/?pg=3955 1:00 Hungary CE%sT 1941 Apr 7 23:00 1:00 C-Eur CE%sT 1945 1:00 Hungary CE%sT 1984 diff --git a/make/modules/java.base/Copy.gmk b/make/modules/java.base/Copy.gmk index 9071f4e6e37..040b7588ba1 100644 --- a/make/modules/java.base/Copy.gmk +++ b/make/modules/java.base/Copy.gmk @@ -182,12 +182,16 @@ endif ################################################################################ -$(eval $(call SetupCopyFiles, COPY_NET_PROPERTIES, \ - FILES := $(TOPDIR)/src/java.base/share/conf/net.properties, \ - DEST := $(CONF_DST_DIR), \ -)) +NET_PROPERTIES_SRCS := $(TOPDIR)/src/java.base/share/conf/net.properties \ + $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/net.properties + +NET_PROPERTIES_DST := $(CONF_DST_DIR)/net.properties + +$(NET_PROPERTIES_DST): $(NET_PROPERTIES_SRCS) + $(call MakeTargetDir) + $(CAT) $(NET_PROPERTIES_SRCS) > $@ -TARGETS += $(COPY_NET_PROPERTIES) +TARGETS += $(NET_PROPERTIES_DST) ifeq ($(call isTargetOs, linux), true) $(eval $(call SetupCopyFiles, COPY_SDP_CONF, \ diff --git a/make/modules/jdk.crypto.ec/Lib.gmk b/make/modules/jdk.crypto.ec/Lib.gmk deleted file mode 100644 index eb1baccc930..00000000000 --- a/make/modules/jdk.crypto.ec/Lib.gmk +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (c) 2011, 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. -# - -include LibCommon.gmk - -################################################################################ - -ifeq ($(ENABLE_INTREE_EC), true) - $(eval $(call SetupJdkLibrary, BUILD_LIBSUNEC, \ - NAME := sunec, \ - TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B, \ - CXXFLAGS := $(CXXFLAGS_JDKLIB), \ - DISABLED_WARNINGS_gcc := sign-compare implicit-fallthrough unused-value, \ - DISABLED_WARNINGS_clang := sign-compare, \ - DISABLED_WARNINGS_microsoft := 4101 4244 4146 4018, \ - LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ - LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := $(LIBCXX), \ - )) - - TARGETS += $(BUILD_LIBSUNEC) -endif - -################################################################################ diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 3bbbea47b8e..55e5026eb38 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -90,11 +90,10 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ SMALL_JAVA := false, \ CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \ - DISABLED_WARNINGS := processing rawtypes cast serial preview, \ + DISABLED_WARNINGS := processing rawtypes cast serial, \ SRC := $(MICROBENCHMARK_SRC), \ BIN := $(MICROBENCHMARK_CLASSES), \ JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management, \ - JAVAC_FLAGS := --enable-preview, \ )) $(BUILD_JDK_MICROBENCHMARK): $(JMH_COMPILE_JARS) diff --git a/src/hotspot/cpu/aarch64/aarch64_sve.ad b/src/hotspot/cpu/aarch64/aarch64_sve.ad index aae3fbf304e..f34d4890c70 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve.ad +++ b/src/hotspot/cpu/aarch64/aarch64_sve.ad @@ -1329,7 +1329,7 @@ instruct vlsrL(vReg dst, vReg shift) %{ instruct vasrB_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 16); - match(Set dst (RShiftVB src shift)); + match(Set dst (RShiftVB src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (B)" %} ins_encode %{ @@ -1348,7 +1348,7 @@ instruct vasrB_imm(vReg dst, vReg src, immI shift) %{ instruct vasrS_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 8); - match(Set dst (RShiftVS src shift)); + match(Set dst (RShiftVS src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (H)" %} ins_encode %{ @@ -1367,7 +1367,7 @@ instruct vasrS_imm(vReg dst, vReg src, immI shift) %{ instruct vasrI_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 4); - match(Set dst (RShiftVI src shift)); + match(Set dst (RShiftVI src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (S)" %} ins_encode %{ @@ -1385,7 +1385,7 @@ instruct vasrI_imm(vReg dst, vReg src, immI shift) %{ instruct vasrL_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 2); - match(Set dst (RShiftVL src shift)); + match(Set dst (RShiftVL src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (D)" %} ins_encode %{ @@ -1403,7 +1403,7 @@ instruct vasrL_imm(vReg dst, vReg src, immI shift) %{ instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 16); - match(Set dst (URShiftVB src shift)); + match(Set dst (URShiftVB src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (B)" %} ins_encode %{ @@ -1426,7 +1426,7 @@ instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{ instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 8); - match(Set dst (URShiftVS src shift)); + match(Set dst (URShiftVS src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (H)" %} ins_encode %{ @@ -1436,7 +1436,7 @@ instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ as_FloatRegister($src$$reg)); return; } - if (con >= 8) { + if (con >= 16) { __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); return; @@ -1449,7 +1449,7 @@ instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 4); - match(Set dst (URShiftVI src shift)); + match(Set dst (URShiftVI src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (S)" %} ins_encode %{ @@ -1467,7 +1467,7 @@ instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{ instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 2); - match(Set dst (URShiftVL src shift)); + match(Set dst (URShiftVL src (RShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (D)" %} ins_encode %{ @@ -1485,7 +1485,7 @@ instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{ instruct vlslB_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 16); - match(Set dst (LShiftVB src shift)); + match(Set dst (LShiftVB src (LShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (B)" %} ins_encode %{ @@ -1503,12 +1503,12 @@ instruct vlslB_imm(vReg dst, vReg src, immI shift) %{ instruct vlslS_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 8); - match(Set dst (LShiftVS src shift)); + match(Set dst (LShiftVS src (LShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (H)" %} ins_encode %{ int con = (int)$shift$$constant; - if (con >= 8) { + if (con >= 16) { __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); return; @@ -1521,7 +1521,7 @@ instruct vlslS_imm(vReg dst, vReg src, immI shift) %{ instruct vlslI_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 4); - match(Set dst (LShiftVI src shift)); + match(Set dst (LShiftVI src (LShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (S)" %} ins_encode %{ @@ -1534,7 +1534,7 @@ instruct vlslI_imm(vReg dst, vReg src, immI shift) %{ instruct vlslL_imm(vReg dst, vReg src, immI shift) %{ predicate(UseSVE > 0 && n->as_Vector()->length() >= 2); - match(Set dst (LShiftVL src shift)); + match(Set dst (LShiftVL src (LShiftCntV shift))); ins_cost(SVE_COST); format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (D)" %} ins_encode %{ diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index 914b84aa902..7fe0861a717 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -727,14 +727,14 @@ instruct $1(vReg dst, vReg shift) %{ ins_pipe(pipe_slow); %}')dnl dnl -dnl VSHIFT_IMM_UNPREDICATE($1, $2, $3, $4, $5 ) -dnl VSHIFT_IMM_UNPREDICATE(insn_name, op_name, size, min_vec_len, insn) +dnl VSHIFT_IMM_UNPREDICATE($1, $2, $3, $4, $5, $6 ) +dnl VSHIFT_IMM_UNPREDICATE(insn_name, op_name, op_name2, size, min_vec_len, insn) define(`VSHIFT_IMM_UNPREDICATE', ` instruct $1(vReg dst, vReg src, immI shift) %{ - predicate(UseSVE > 0 && n->as_Vector()->length() >= $4); - match(Set dst ($2 src shift)); + predicate(UseSVE > 0 && n->as_Vector()->length() >= $5); + match(Set dst ($2 src ($3 shift))); ins_cost(SVE_COST); - format %{ "$5 $dst, $src, $shift\t# vector (sve) ($3)" %} + format %{ "$6 $dst, $src, $shift\t# vector (sve) ($4)" %} ins_encode %{ int con = (int)$shift$$constant;dnl ifelse(eval(index(`$1', `vasr') == 0 || index(`$1', `vlsr') == 0), 1, ` @@ -743,16 +743,21 @@ ifelse(eval(index(`$1', `vasr') == 0 || index(`$1', `vlsr') == 0), 1, ` as_FloatRegister($src$$reg)); return; }')dnl -ifelse(eval(index(`$1', `vasr') == 0), 1, `ifelse(eval(index(`$3', `B') == 0), 1, ` - if (con >= 8) con = 7;')ifelse(eval(index(`$3', `H') == 0), 1, ` +ifelse(eval(index(`$1', `vasr') == 0), 1, `ifelse(eval(index(`$4', `B') == 0), 1, ` + if (con >= 8) con = 7;')ifelse(eval(index(`$4', `H') == 0), 1, ` if (con >= 16) con = 15;')')dnl -ifelse(eval((index(`$1', `vlsl') == 0 || index(`$1', `vlsr') == 0) && (index(`$3', `B') == 0 || index(`$3', `H') == 0)), 1, ` +ifelse(eval(index(`$1', `vlsl') == 0 || index(`$1', `vlsr') == 0), 1, `ifelse(eval(index(`$4', `B') == 0), 1, ` if (con >= 8) { __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); return; - }') - __ $5(as_FloatRegister($dst$$reg), __ $3, + }')ifelse(eval(index(`$4', `H') == 0), 1, ` + if (con >= 16) { + __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + return; + }')') + __ $6(as_FloatRegister($dst$$reg), __ $4, as_FloatRegister($src$$reg), con); %} ins_pipe(pipe_slow); @@ -786,18 +791,18 @@ VSHIFT_TRUE_PREDICATE(vlsrB, URShiftVB, B, 16, sve_lsr) VSHIFT_TRUE_PREDICATE(vlsrS, URShiftVS, H, 8, sve_lsr) VSHIFT_TRUE_PREDICATE(vlsrI, URShiftVI, S, 4, sve_lsr) VSHIFT_TRUE_PREDICATE(vlsrL, URShiftVL, D, 2, sve_lsr) -VSHIFT_IMM_UNPREDICATE(vasrB_imm, RShiftVB, B, 16, sve_asr) -VSHIFT_IMM_UNPREDICATE(vasrS_imm, RShiftVS, H, 8, sve_asr) -VSHIFT_IMM_UNPREDICATE(vasrI_imm, RShiftVI, S, 4, sve_asr) -VSHIFT_IMM_UNPREDICATE(vasrL_imm, RShiftVL, D, 2, sve_asr) -VSHIFT_IMM_UNPREDICATE(vlsrB_imm, URShiftVB, B, 16, sve_lsr) -VSHIFT_IMM_UNPREDICATE(vlsrS_imm, URShiftVS, H, 8, sve_lsr) -VSHIFT_IMM_UNPREDICATE(vlsrI_imm, URShiftVI, S, 4, sve_lsr) -VSHIFT_IMM_UNPREDICATE(vlsrL_imm, URShiftVL, D, 2, sve_lsr) -VSHIFT_IMM_UNPREDICATE(vlslB_imm, LShiftVB, B, 16, sve_lsl) -VSHIFT_IMM_UNPREDICATE(vlslS_imm, LShiftVS, H, 8, sve_lsl) -VSHIFT_IMM_UNPREDICATE(vlslI_imm, LShiftVI, S, 4, sve_lsl) -VSHIFT_IMM_UNPREDICATE(vlslL_imm, LShiftVL, D, 2, sve_lsl) +VSHIFT_IMM_UNPREDICATE(vasrB_imm, RShiftVB, RShiftCntV, B, 16, sve_asr) +VSHIFT_IMM_UNPREDICATE(vasrS_imm, RShiftVS, RShiftCntV, H, 8, sve_asr) +VSHIFT_IMM_UNPREDICATE(vasrI_imm, RShiftVI, RShiftCntV, S, 4, sve_asr) +VSHIFT_IMM_UNPREDICATE(vasrL_imm, RShiftVL, RShiftCntV, D, 2, sve_asr) +VSHIFT_IMM_UNPREDICATE(vlsrB_imm, URShiftVB, RShiftCntV, B, 16, sve_lsr) +VSHIFT_IMM_UNPREDICATE(vlsrS_imm, URShiftVS, RShiftCntV, H, 8, sve_lsr) +VSHIFT_IMM_UNPREDICATE(vlsrI_imm, URShiftVI, RShiftCntV, S, 4, sve_lsr) +VSHIFT_IMM_UNPREDICATE(vlsrL_imm, URShiftVL, RShiftCntV, D, 2, sve_lsr) +VSHIFT_IMM_UNPREDICATE(vlslB_imm, LShiftVB, LShiftCntV, B, 16, sve_lsl) +VSHIFT_IMM_UNPREDICATE(vlslS_imm, LShiftVS, LShiftCntV, H, 8, sve_lsl) +VSHIFT_IMM_UNPREDICATE(vlslI_imm, LShiftVI, LShiftCntV, S, 4, sve_lsl) +VSHIFT_IMM_UNPREDICATE(vlslL_imm, LShiftVL, LShiftCntV, D, 2, sve_lsl) VSHIFT_COUNT(vshiftcntB, B, 16, T_BYTE) VSHIFT_COUNT(vshiftcntS, H, 8, T_SHORT) VSHIFT_COUNT(vshiftcntI, S, 4, T_INT) diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 294b6b13495..9ad1360fa91 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -93,6 +93,8 @@ define_pd_global(intx, InlineSmallCode, 1000); "Use SIMD instructions in generated array equals code") \ product(bool, UseSimpleArrayEquals, false, \ "Use simpliest and shortest implementation for array equals") \ + product(bool, UseSIMDForBigIntegerShiftIntrinsics, true, \ + "Use SIMD instructions for left/right shift of BigInteger") \ product(bool, AvoidUnalignedAccesses, false, \ "Avoid generating unaligned memory accesses") \ product(bool, UseLSE, false, \ diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 44b9f59bbb3..09632154630 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -551,7 +551,9 @@ void InterpreterMacroAssembler::remove_activation( br(Assembler::AL, fast_path); bind(slow_path); push(state); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind)); + set_last_Java_frame(esp, rfp, (address)pc(), rscratch1); + super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), rthread); + reset_last_Java_frame(true); pop(state); bind(fast_path); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index a230e4e5bba..b39e793e850 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -3968,6 +3968,238 @@ class StubGenerator: public StubCodeGenerator { return start; } + // 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 start = __ pc(); + + Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, 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 newArrCur = rscratch1; + Register shiftRevCount = rscratch2; + Register oldArrCur = r13; + Register oldArrNext = r14; + + FloatRegister oldElem0 = v0; + FloatRegister oldElem1 = v1; + FloatRegister newElem = v2; + FloatRegister shiftVCount = v3; + FloatRegister shiftVRevCount = v4; + + __ cbz(idx, Exit); + + __ add(newArr, newArr, newIdx, Assembler::LSL, 2); + + // left shift count + __ movw(shiftRevCount, 32); + __ subw(shiftRevCount, shiftRevCount, shiftCount); + + // numIter too small to allow a 4-words SIMD loop, rolling back + __ cmp(numIter, (u1)4); + __ br(Assembler::LT, ShiftThree); + + __ dup(shiftVCount, __ T4S, shiftCount); + __ dup(shiftVRevCount, __ T4S, shiftRevCount); + __ negr(shiftVCount, __ T4S, shiftVCount); + + __ BIND(ShiftSIMDLoop); + + // Calculate the load addresses + __ sub(idx, idx, 4); + __ add(oldArrNext, oldArr, idx, Assembler::LSL, 2); + __ add(newArrCur, newArr, idx, Assembler::LSL, 2); + __ add(oldArrCur, oldArrNext, 4); + + // Load 4 words and process + __ ld1(oldElem0, __ T4S, Address(oldArrCur)); + __ ld1(oldElem1, __ T4S, Address(oldArrNext)); + __ ushl(oldElem0, __ T4S, oldElem0, shiftVCount); + __ ushl(oldElem1, __ T4S, oldElem1, shiftVRevCount); + __ orr(newElem, __ T16B, oldElem0, oldElem1); + __ st1(newElem, __ T4S, Address(newArrCur)); + + __ cmp(idx, (u1)4); + __ br(Assembler::LT, ShiftTwoLoop); + __ b(ShiftSIMDLoop); + + __ BIND(ShiftTwoLoop); + __ cbz(idx, Exit); + __ cmp(idx, (u1)1); + __ br(Assembler::EQ, ShiftOne); + + // Calculate the load addresses + __ sub(idx, idx, 2); + __ add(oldArrNext, oldArr, idx, Assembler::LSL, 2); + __ add(newArrCur, newArr, idx, Assembler::LSL, 2); + __ add(oldArrCur, oldArrNext, 4); + + // Load 2 words and process + __ ld1(oldElem0, __ T2S, Address(oldArrCur)); + __ ld1(oldElem1, __ T2S, Address(oldArrNext)); + __ ushl(oldElem0, __ T2S, oldElem0, shiftVCount); + __ ushl(oldElem1, __ T2S, oldElem1, shiftVRevCount); + __ orr(newElem, __ T8B, oldElem0, oldElem1); + __ st1(newElem, __ T2S, Address(newArrCur)); + __ b(ShiftTwoLoop); + + __ BIND(ShiftThree); + __ tbz(idx, 1, ShiftOne); + __ tbz(idx, 0, ShiftTwo); + __ ldrw(r10, Address(oldArr, 12)); + __ ldrw(r11, Address(oldArr, 8)); + __ lsrvw(r10, r10, shiftCount); + __ lslvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, Address(newArr, 8)); + + __ BIND(ShiftTwo); + __ ldrw(r10, Address(oldArr, 8)); + __ ldrw(r11, Address(oldArr, 4)); + __ lsrvw(r10, r10, shiftCount); + __ lslvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, Address(newArr, 4)); + + __ BIND(ShiftOne); + __ ldrw(r10, Address(oldArr, 4)); + __ ldrw(r11, Address(oldArr)); + __ lsrvw(r10, r10, shiftCount); + __ lslvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, Address(newArr)); + + __ BIND(Exit); + __ ret(lr); + + return start; + } + + // 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 start = __ pc(); + + Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, Exit; + + Register newArr = c_rarg0; + Register oldArr = c_rarg1; + Register newIdx = c_rarg2; + Register shiftCount = c_rarg3; + Register numIter = c_rarg4; + + Register shiftRevCount = rscratch1; + Register oldArrNext = rscratch2; + + FloatRegister oldElem0 = v0; + FloatRegister oldElem1 = v1; + FloatRegister newElem = v2; + FloatRegister shiftVCount = v3; + FloatRegister shiftVRevCount = v4; + + __ cbz(numIter, Exit); + + __ add(oldArrNext, oldArr, 4); + __ add(newArr, newArr, newIdx, Assembler::LSL, 2); + + // right shift count + __ movw(shiftRevCount, 32); + __ subw(shiftRevCount, shiftRevCount, shiftCount); + + // numIter too small to allow a 4-words SIMD loop, rolling back + __ cmp(numIter, (u1)4); + __ br(Assembler::LT, ShiftThree); + + __ dup(shiftVCount, __ T4S, shiftCount); + __ dup(shiftVRevCount, __ T4S, shiftRevCount); + __ negr(shiftVRevCount, __ T4S, shiftVRevCount); + + __ BIND(ShiftSIMDLoop); + + // load 4 words and process + __ ld1(oldElem0, __ T4S, __ post(oldArr, 16)); + __ ld1(oldElem1, __ T4S, __ post(oldArrNext, 16)); + __ ushl(oldElem0, __ T4S, oldElem0, shiftVCount); + __ ushl(oldElem1, __ T4S, oldElem1, shiftVRevCount); + __ orr(newElem, __ T16B, oldElem0, oldElem1); + __ st1(newElem, __ T4S, __ post(newArr, 16)); + __ sub(numIter, numIter, 4); + + __ cmp(numIter, (u1)4); + __ br(Assembler::LT, ShiftTwoLoop); + __ b(ShiftSIMDLoop); + + __ BIND(ShiftTwoLoop); + __ cbz(numIter, Exit); + __ cmp(numIter, (u1)1); + __ br(Assembler::EQ, ShiftOne); + + // load 2 words and process + __ ld1(oldElem0, __ T2S, __ post(oldArr, 8)); + __ ld1(oldElem1, __ T2S, __ post(oldArrNext, 8)); + __ ushl(oldElem0, __ T2S, oldElem0, shiftVCount); + __ ushl(oldElem1, __ T2S, oldElem1, shiftVRevCount); + __ orr(newElem, __ T8B, oldElem0, oldElem1); + __ st1(newElem, __ T2S, __ post(newArr, 8)); + __ sub(numIter, numIter, 2); + __ b(ShiftTwoLoop); + + __ BIND(ShiftThree); + __ ldrw(r10, __ post(oldArr, 4)); + __ ldrw(r11, __ post(oldArrNext, 4)); + __ lslvw(r10, r10, shiftCount); + __ lsrvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, __ post(newArr, 4)); + __ tbz(numIter, 1, Exit); + __ tbz(numIter, 0, ShiftOne); + + __ BIND(ShiftTwo); + __ ldrw(r10, __ post(oldArr, 4)); + __ ldrw(r11, __ post(oldArrNext, 4)); + __ lslvw(r10, r10, shiftCount); + __ lsrvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, __ post(newArr, 4)); + + __ BIND(ShiftOne); + __ ldrw(r10, Address(oldArr)); + __ ldrw(r11, Address(oldArrNext)); + __ lslvw(r10, r10, shiftCount); + __ lsrvw(r11, r11, shiftRevCount); + __ orrw(r12, r10, r11); + __ strw(r12, Address(newArr)); + + __ BIND(Exit); + __ ret(lr); + + return start; + } + void ghash_multiply(FloatRegister result_lo, FloatRegister result_hi, FloatRegister a, FloatRegister b, FloatRegister a1_xor_a0, FloatRegister tmp1, FloatRegister tmp2, FloatRegister tmp3, FloatRegister tmp4) { @@ -6224,6 +6456,11 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_mulAdd = generate_mulAdd(); } + if (UseSIMDForBigIntegerShiftIntrinsics) { + StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); + StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); + } + if (UseMontgomeryMultiplyIntrinsic) { StubCodeMark mark(this, "StubRoutines", "montgomeryMultiply"); MontgomeryMultiplyGenerator g(_masm, /*squaring*/false); diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 3155d29e8a4..18f56a527ab 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -401,7 +401,7 @@ void VM_Version::initialize() { warning("SVE does not support vector length less than 16 bytes. Disabling SVE."); UseSVE = 0; } else if ((MaxVectorSize % 16) == 0 && is_power_of_2(MaxVectorSize)) { - int new_vl = set_and_get_current_sve_vector_lenght(MaxVectorSize); + int new_vl = set_and_get_current_sve_vector_length(MaxVectorSize); _initial_sve_vector_length = new_vl; // Update MaxVectorSize to the largest supported value. if (new_vl < 0) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index f0b6b650724..45838f87072 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -51,7 +51,7 @@ class VM_Version : public Abstract_VM_Version { // Sets the SVE length and returns a new actual value or negative on error. // If the len is larger than the system largest supported SVE vector length, // the function sets the largest supported value. - static int set_and_get_current_sve_vector_lenght(int len); + static int set_and_get_current_sve_vector_length(int len); static int get_current_sve_vector_length(); public: diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 4e707bdfd45..2588f7a211c 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2062,97 +2062,78 @@ static int frame_slots_bias(int reg_enc, PhaseRegAlloc* ra_) { } const bool Matcher::match_rule_supported(int opcode) { - if (!has_match_rule(opcode)) - return false; + if (!has_match_rule(opcode)) { + return false; // no match rule present + } - bool ret_value = true; switch (opcode) { - case Op_SqrtD: - return VM_Version::has_fsqrt(); - case Op_CountLeadingZerosI: - case Op_CountLeadingZerosL: - if (!UseCountLeadingZerosInstructionsPPC64) - return false; - break; - case Op_CountTrailingZerosI: - case Op_CountTrailingZerosL: - if (!UseCountLeadingZerosInstructionsPPC64 && - !UseCountTrailingZerosInstructionsPPC64) - return false; - break; - - case Op_PopCountI: - case Op_PopCountL: - return (UsePopCountInstruction && VM_Version::has_popcntw()); - - case Op_StrComp: - return SpecialStringCompareTo; - case Op_StrEquals: - return SpecialStringEquals; - case Op_StrIndexOf: - case Op_StrIndexOfChar: - return SpecialStringIndexOf; - case Op_AddVB: - case Op_AddVS: - case Op_AddVI: - case Op_AddVF: - case Op_AddVD: - case Op_SubVB: - case Op_SubVS: - case Op_SubVI: - case Op_SubVF: - case Op_SubVD: - case Op_MulVS: - case Op_MulVF: - case Op_MulVD: - case Op_DivVF: - case Op_DivVD: - case Op_AbsVF: - case Op_AbsVD: - case Op_NegVF: - case Op_NegVD: - case Op_SqrtVF: - case Op_SqrtVD: - case Op_AddVL: - case Op_SubVL: - case Op_MulVI: - case Op_RoundDoubleModeV: - return SuperwordUseVSX; - case Op_PopCountVI: - return (SuperwordUseVSX && UsePopCountInstruction); - case Op_FmaVF: - case Op_FmaVD: - return (SuperwordUseVSX && UseFMA); - case Op_Digit: - return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isDigit); - case Op_LowerCase: - return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isLowerCase); - case Op_UpperCase: - return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isUpperCase); - case Op_Whitespace: - return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isWhitespace); - - case Op_CacheWB: - case Op_CacheWBPreSync: - case Op_CacheWBPostSync: - if (!VM_Version::supports_data_cache_line_flush()) { - ret_value = false; - } - break; + case Op_SqrtD: + return VM_Version::has_fsqrt(); + case Op_CountLeadingZerosI: + case Op_CountLeadingZerosL: + return UseCountLeadingZerosInstructionsPPC64; + case Op_CountTrailingZerosI: + case Op_CountTrailingZerosL: + return (UseCountLeadingZerosInstructionsPPC64 || UseCountTrailingZerosInstructionsPPC64); + case Op_PopCountI: + case Op_PopCountL: + return (UsePopCountInstruction && VM_Version::has_popcntw()); + + case Op_AddVB: + case Op_AddVS: + case Op_AddVI: + case Op_AddVF: + case Op_AddVD: + case Op_SubVB: + case Op_SubVS: + case Op_SubVI: + case Op_SubVF: + case Op_SubVD: + case Op_MulVS: + case Op_MulVF: + case Op_MulVD: + case Op_DivVF: + case Op_DivVD: + case Op_AbsVF: + case Op_AbsVD: + case Op_NegVF: + case Op_NegVD: + case Op_SqrtVF: + case Op_SqrtVD: + case Op_AddVL: + case Op_SubVL: + case Op_MulVI: + case Op_RoundDoubleModeV: + return SuperwordUseVSX; + case Op_PopCountVI: + return (SuperwordUseVSX && UsePopCountInstruction); + case Op_FmaVF: + case Op_FmaVD: + return (SuperwordUseVSX && UseFMA); + + case Op_Digit: + return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isDigit); + case Op_LowerCase: + return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isLowerCase); + case Op_UpperCase: + return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isUpperCase); + case Op_Whitespace: + return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isWhitespace); + + case Op_CacheWB: + case Op_CacheWBPreSync: + case Op_CacheWBPostSync: + return VM_Version::supports_data_cache_line_flush(); } - return ret_value; // Per default match rules are supported. + return true; // Per default match rules are supported. } const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { - - // TODO - // identify extra cases that we might want to provide match rules for - // e.g. Op_ vector nodes and other intrinsics while guarding with vlen - bool ret_value = match_rule_supported(opcode); - // Add rules here. - - return ret_value; // Per default match rules are supported. + if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) { + return false; + } + return true; // Per default match rules are supported. } const bool Matcher::has_predicated_vectors(void) { @@ -6569,6 +6550,23 @@ instruct storeV16(indirect mem, vecX src) %{ ins_pipe(pipe_class_default); %} +// Reinterpret: only one vector size used: either L or X +instruct reinterpretL(iRegLdst dst) %{ + match(Set dst (VectorReinterpret dst)); + ins_cost(0); + format %{ "reinterpret $dst" %} + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_empty); +%} + +instruct reinterpretX(vecX dst) %{ + match(Set dst (VectorReinterpret dst)); + ins_cost(0); + format %{ "reinterpret $dst" %} + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_empty); +%} + // Store Compressed Oop instruct storeN(memory dst, iRegN_P2N src) %{ match(Set dst (StoreN dst src)); @@ -12599,9 +12597,10 @@ instruct indexOfChar_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U); ins_cost(180); - format %{ "String IndexOfChar $haystack[0..$haycnt], $ch" + format %{ "StringUTF16 IndexOfChar $haystack[0..$haycnt], $ch" " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ __ string_indexof_char($result$$Register, @@ -12612,6 +12611,25 @@ instruct indexOfChar_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, ins_pipe(pipe_class_compare); %} +instruct indexOfChar_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + iRegIsrc ch, iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); + effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L); + ins_cost(180); + + format %{ "StringLatin1 IndexOfChar $haystack[0..$haycnt], $ch" + " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + ins_encode %{ + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + $ch$$Register, 0 /* this is not used if the character is already in a register */, + $tmp1$$Register, $tmp2$$Register, true /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + instruct indexOf_imm_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, uimmI15 needlecntImm, iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index e533e407b15..de1565194ed 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1511,60 +1511,28 @@ static Register reg_to_register_object(int register_encoding) { } const bool Matcher::match_rule_supported(int opcode) { - if (!has_match_rule(opcode)) return false; + if (!has_match_rule(opcode)) { + return false; // no match rule present + } switch (opcode) { - case Op_CountLeadingZerosI: - case Op_CountLeadingZerosL: - case Op_CountTrailingZerosI: - case Op_CountTrailingZerosL: - // Implementation requires FLOGR instruction, which is available since z9. - return true; - case Op_ReverseBytesI: case Op_ReverseBytesL: return UseByteReverseInstruction; - - // PopCount supported by H/W from z/Architecture G5 (z196) on. case Op_PopCountI: case Op_PopCountL: - return UsePopCountInstruction && VM_Version::has_PopCount(); - - case Op_StrComp: - return SpecialStringCompareTo; - case Op_StrEquals: - return SpecialStringEquals; - case Op_StrIndexOf: - case Op_StrIndexOfChar: - return SpecialStringIndexOf; - - case Op_GetAndAddI: - case Op_GetAndAddL: - return true; - // return VM_Version::has_AtomicMemWithImmALUOps(); - case Op_GetAndSetI: - case Op_GetAndSetL: - case Op_GetAndSetP: - case Op_GetAndSetN: - return true; // General CAS implementation, always available. - - default: - return true; // Per default match rules are supported. - // BUT: make sure match rule is not disabled by a false predicate! + // PopCount supported by H/W from z/Architecture G5 (z196) on. + return (UsePopCountInstruction && VM_Version::has_PopCount()); } - return true; // Per default match rules are supported. - // BUT: make sure match rule is not disabled by a false predicate! + return true; // Per default match rules are supported. } const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { - // TODO - // Identify extra cases that we might want to provide match rules for - // e.g. Op_ vector nodes and other intrinsics while guarding with vlen. - bool ret_value = match_rule_supported(opcode); - // Add rules here. - - return ret_value; // Per default match rules are supported. + if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) { + return false; + } + return true; // Per default match rules are supported. } const bool Matcher::has_predicated_vectors(void) { @@ -10154,8 +10122,9 @@ instruct string_compareUL(iRegP str1, iRegP str2, rarg2RegI cnt1, rarg5RegI cnt2 instruct indexOfChar_U(iRegP haystack, iRegI haycnt, iRegI ch, iRegI result, roddRegL oddReg, revenRegL evenReg, flagsReg cr) %{ match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); effect(TEMP_DEF result, TEMP evenReg, TEMP oddReg, KILL cr); // R0, R1 are killed, too. + predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U); ins_cost(200); - format %{ "String IndexOfChar [0..$haycnt]($haystack), $ch -> $result" %} + format %{ "StringUTF16 IndexOfChar [0..$haycnt]($haystack), $ch -> $result" %} ins_encode %{ __ string_indexof_char($result$$Register, $haystack$$Register, $haycnt$$Register, @@ -10165,6 +10134,21 @@ instruct indexOfChar_U(iRegP haystack, iRegI haycnt, iRegI ch, iRegI result, rod ins_pipe(pipe_class_dummy); %} +instruct indexOfChar_L(iRegP haystack, iRegI haycnt, iRegI ch, iRegI result, roddRegL oddReg, revenRegL evenReg, flagsReg cr) %{ + match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); + effect(TEMP_DEF result, TEMP evenReg, TEMP oddReg, KILL cr); // R0, R1 are killed, too. + predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L); + ins_cost(200); + format %{ "StringLatin1 IndexOfChar [0..$haycnt]($haystack), $ch -> $result" %} + ins_encode %{ + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + $ch$$Register, 0 /* unused, ch is in register */, + $oddReg$$Register, $evenReg$$Register, true /*is_byte*/); + %} + ins_pipe(pipe_class_dummy); +%} + instruct indexOf_imm1_U(iRegP haystack, iRegI haycnt, immP needle, immI_1 needlecnt, iRegI result, roddRegL oddReg, revenRegL evenReg, flagsReg cr) %{ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); effect(TEMP_DEF result, TEMP evenReg, TEMP oddReg, KILL cr); // R0, R1 are killed, too. @@ -10791,7 +10775,7 @@ instruct Repl2F_imm0(iRegL dst, immFp0 src) %{ ins_pipe(pipe_class_dummy); %} -// Store +// Load/Store vector // Store Aligned Packed Byte register to memory (8 Bytes). instruct storeA8B(memory mem, iRegL src) %{ @@ -10805,8 +10789,6 @@ instruct storeA8B(memory mem, iRegL src) %{ ins_pipe(pipe_class_dummy); %} -// Load - instruct loadV8(iRegL dst, memory mem) %{ match(Set dst (LoadVector mem)); predicate(n->as_LoadVector()->memory_size() == 8); @@ -10818,6 +10800,15 @@ instruct loadV8(iRegL dst, memory mem) %{ ins_pipe(pipe_class_dummy); %} +// Reinterpret: only one vector size used +instruct reinterpret(iRegL dst) %{ + match(Set dst (VectorReinterpret dst)); + ins_cost(0); + format %{ "reinterpret $dst" %} + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_dummy); +%} + //----------POPULATION COUNT RULES-------------------------------------------- // Byte reverse diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index d37995357b3..0a769c9401f 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -836,7 +836,7 @@ void VM_Version::determine_features() { code_end-code, cbuf_size, cbuf_size-(code_end-code)); // Use existing decode function. This enables the [MachCode] format which is needed to DecodeErrorFile. - Disassembler::decode(&cbuf, code, code_end, tty); + Disassembler::decode(code, code_end, tty); } // Prepare for detection code execution and clear work buffer. diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 1f6b196d3ce..3933bac000f 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -9803,7 +9803,7 @@ void Assembler::cmpq(Register dst, int32_t imm32) { void Assembler::cmpq(Address dst, Register src) { InstructionMark im(this); - emit_int16(get_prefixq(dst, src), 0x3B); + emit_int16(get_prefixq(dst, src), 0x39); emit_operand(src, dst); } diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index 2c7f861b1a2..9c1376a33c6 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -605,6 +605,10 @@ void InterpreterMacroAssembler::push_i(Register r) { push(r); } +void InterpreterMacroAssembler::push_i_or_ptr(Register r) { + push(r); +} + void InterpreterMacroAssembler::push_f(XMMRegister r) { subptr(rsp, wordSize); movflt(Address(rsp, 0), r); @@ -999,9 +1003,11 @@ void InterpreterMacroAssembler::remove_activation( jmp(fast_path); bind(slow_path); push(state); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind)); - pop(state); + set_last_Java_frame(rthread, noreg, rbp, (address)pc()); + super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), rthread); NOT_LP64(get_thread(rthread);) // call_VM clobbered it, restore + reset_last_Java_frame(rthread, true); + pop(state); bind(fast_path); // get the value of _do_not_unlock_if_synchronized into rdx diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index 3e2e33278a1..288b1bd1dfe 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -139,9 +139,18 @@ class InterpreterMacroAssembler: public MacroAssembler { // Expression stack void pop_ptr(Register r = rax); void pop_i(Register r = rax); + + // On x86, pushing a ptr or an int is semantically identical, but we + // maintain a distinction for clarity and for making it easier to change + // semantics in the future void push_ptr(Register r = rax); void push_i(Register r = rax); + // push_i_or_ptr is provided for when explicitly allowing either a ptr or + // an int might have some advantage, while still documenting the fact that a + // ptr might be pushed to the stack. + void push_i_or_ptr(Register r = rax); + void push_f(XMMRegister r); void pop_f(XMMRegister r); void pop_d(XMMRegister r); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index a8da3aa17b8..81303ea76c4 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -2765,7 +2765,7 @@ void MacroAssembler::safepoint_poll(Label& slow_path, Register thread_reg, bool if (at_return) { // Note that when in_nmethod is set, the stack pointer is incremented before the poll. Therefore, // we may safely use rsp instead to perform the stack watermark check. - cmpq(Address(thread_reg, Thread::polling_word_offset()), in_nmethod ? rsp : rbp); + cmpq(in_nmethod ? rsp : rbp, Address(thread_reg, Thread::polling_word_offset())); jcc(Assembler::above, slow_path); return; } diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index f07eb9664ec..072b3d144fa 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -1761,9 +1761,6 @@ void TemplateInterpreterGenerator::set_vtos_entry_points(Template* t, address& vep) { assert(t->is_valid() && t->tos_in() == vtos, "illegal template"); Label L; - aep = __ pc(); // atos entry point - __ push_ptr(); - __ jmp(L); #ifndef _LP64 fep = __ pc(); // ftos entry point __ push(ftos); @@ -1782,8 +1779,8 @@ void TemplateInterpreterGenerator::set_vtos_entry_points(Template* t, lep = __ pc(); // ltos entry point __ push_l(); __ jmp(L); - bep = cep = sep = iep = __ pc(); // [bcsi]tos entry point - __ push_i(); + aep = bep = cep = sep = iep = __ pc(); // [abcsi]tos entry point + __ push_i_or_ptr(); vep = __ pc(); // vtos entry point __ bind(L); generate_and_dispatch(t); diff --git a/src/hotspot/cpu/x86/vm_version_ext_x86.cpp b/src/hotspot/cpu/x86/vm_version_ext_x86.cpp index 8042a8f1c69..35d07d71e46 100644 --- a/src/hotspot/cpu/x86/vm_version_ext_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_ext_x86.cpp @@ -256,7 +256,7 @@ const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1); const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256; const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096; char* VM_Version_Ext::_cpu_brand_string = NULL; -jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0; +int64_t VM_Version_Ext::_max_qualified_cpu_frequency = 0; int VM_Version_Ext::_no_of_threads = 0; int VM_Version_Ext::_no_of_cores = 0; @@ -644,56 +644,50 @@ const char* VM_Version_Ext::cpu_description(void) { } /** - * See Intel Application note 485 (chapter 10) for details - * on frequency extraction from cpu brand string. - * http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf + * For information about extracting the frequency from the cpu brand string, please see: * + * Intel Processor Identification and the CPUID Instruction + * Application Note 485 + * May 2012 + * + * The return value is the frequency in Hz. */ -jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) { - // get brand string +int64_t VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) { const char* const brand_string = cpu_brand_string(); if (brand_string == NULL) { return 0; } - - const u8 MEGA = 1000000; - u8 multiplier = 0; - jlong frequency = 0; - - // the frequency information in the cpu brand string - // is given in either of two formats "x.xxyHz" or "xxxxyHz", - // where y=M,G,T and x is digits - const char* Hz_location = strchr(brand_string, 'H'); - - if (Hz_location != NULL) { - if (*(Hz_location + 1) == 'z') { - // switch on y in "yHz" - switch(*(Hz_location - 1)) { - case 'M' : - // Set multiplier to frequency is in Hz - multiplier = MEGA; - break; - case 'G' : - multiplier = MEGA * 1000; - break; - case 'T' : - multiplier = MEGA * 1000 * 1000; - break; + const int64_t MEGA = 1000000; + int64_t multiplier = 0; + int64_t frequency = 0; + uint8_t idx = 0; + // The brand string buffer is at most 48 bytes. + // -2 is to prevent buffer overrun when looking for y in yHz, as z is +2 from y. + for (; idx < 48-2; ++idx) { + // Format is either "x.xxyHz" or "xxxxyHz", where y=M, G, T and x are digits. + // Search brand string for "yHz" where y is M, G, or T. + if (brand_string[idx+1] == 'H' && brand_string[idx+2] == 'z') { + if (brand_string[idx] == 'M') { + multiplier = MEGA; + } else if (brand_string[idx] == 'G') { + multiplier = MEGA * 1000; + } else if (brand_string[idx] == 'T') { + multiplier = MEGA * MEGA; } + break; } } - if (multiplier > 0) { - // compute frequency (in Hz) from brand string - if (*(Hz_location - 4) == '.') { // if format is "x.xx" - frequency = (jlong)(*(Hz_location - 5) - '0') * (multiplier); - frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10); - frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100); + // Compute freqency (in Hz) from brand string. + if (brand_string[idx-3] == '.') { // if format is "x.xx" + frequency = (brand_string[idx-4] - '0') * multiplier; + frequency += (brand_string[idx-2] - '0') * multiplier / 10; + frequency += (brand_string[idx-1] - '0') * multiplier / 100; } else { // format is "xxxx" - frequency = (jlong)(*(Hz_location - 5) - '0') * 1000; - frequency += (jlong)(*(Hz_location - 4) - '0') * 100; - frequency += (jlong)(*(Hz_location - 3) - '0') * 10; - frequency += (jlong)(*(Hz_location - 2) - '0'); + frequency = (brand_string[idx-4] - '0') * 1000; + frequency += (brand_string[idx-3] - '0') * 100; + frequency += (brand_string[idx-2] - '0') * 10; + frequency += (brand_string[idx-1] - '0'); frequency *= multiplier; } } @@ -701,7 +695,7 @@ jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) { } -jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) { +int64_t VM_Version_Ext::maximum_qualified_cpu_frequency(void) { if (_max_qualified_cpu_frequency == 0) { _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string(); } diff --git a/src/hotspot/cpu/x86/vm_version_ext_x86.hpp b/src/hotspot/cpu/x86/vm_version_ext_x86.hpp index 1a2134d8561..2d318dd390e 100644 --- a/src/hotspot/cpu/x86/vm_version_ext_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_ext_x86.hpp @@ -55,7 +55,7 @@ class VM_Version_Ext : public VM_Version { static int _no_of_cores; static int _no_of_packages; static char* _cpu_brand_string; - static jlong _max_qualified_cpu_frequency; + static int64_t _max_qualified_cpu_frequency; static const char* cpu_family_description(void); static const char* cpu_model_description(void); @@ -72,7 +72,7 @@ class VM_Version_Ext : public VM_Version { // Returns bytes written excluding termninating null byte. static size_t cpu_write_support_string(char* const buf, size_t buf_len); static void resolve_cpu_information_details(void); - static jlong max_qualified_cpu_freq_from_brand_string(void); + static int64_t max_qualified_cpu_freq_from_brand_string(void); public: // Offsets for cpuid asm stub brand string @@ -93,7 +93,7 @@ class VM_Version_Ext : public VM_Version { static int number_of_cores(void); static int number_of_sockets(void); - static jlong maximum_qualified_cpu_frequency(void); + static int64_t maximum_qualified_cpu_frequency(void); static bool supports_tscinv_ext(void); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 318345b1ffb..bcb17032486 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -4424,9 +4424,8 @@ instruct insert8D(vec dst, vec src, regD val, immI idx, rRegL tmp, legVec vtmp) // =======================Int Reduction========================================== -instruct reductionI(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_INT && - vector_length(n->in(2)) < 16); // src2 +instruct reductionI(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ + predicate(vector_element_basic_type(n->in(2)) == T_INT); // src2 match(Set dst (AddReductionVI src1 src2)); match(Set dst (MulReductionVI src1 src2)); match(Set dst (AndReductionV src1 src2)); @@ -4444,32 +4443,11 @@ instruct reductionI(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtmp2) %{ ins_pipe( pipe_slow ); %} -instruct reduction16I(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_INT && - vector_length(n->in(2)) == 16); // src2 - match(Set dst (AddReductionVI src1 src2)); - match(Set dst (MulReductionVI src1 src2)); - match(Set dst (AndReductionV src1 src2)); - match(Set dst ( OrReductionV src1 src2)); - match(Set dst (XorReductionV src1 src2)); - match(Set dst (MinReductionV src1 src2)); - match(Set dst (MaxReductionV src1 src2)); - effect(TEMP vtmp1, TEMP vtmp2); - format %{ "vector_reduction_int $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} - ins_encode %{ - int opcode = this->ideal_Opcode(); - int vlen = vector_length(this, $src2); - __ reduceI(opcode, vlen, $dst$$Register, $src1$$Register, $src2$$XMMRegister, $vtmp1$$XMMRegister, $vtmp2$$XMMRegister); -%} - ins_pipe( pipe_slow ); -%} - // =======================Long Reduction========================================== #ifdef _LP64 -instruct reductionL(rRegL dst, rRegL src1, vec src2, vec vtmp1, vec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_LONG && - vector_length(n->in(2)) < 8); // src2 +instruct reductionL(rRegL dst, rRegL src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ + predicate(vector_element_basic_type(n->in(2)) == T_LONG && !VM_Version::supports_avx512dq()); match(Set dst (AddReductionVL src1 src2)); match(Set dst (MulReductionVL src1 src2)); match(Set dst (AndReductionV src1 src2)); @@ -4487,9 +4465,8 @@ instruct reductionL(rRegL dst, rRegL src1, vec src2, vec vtmp1, vec vtmp2) %{ ins_pipe( pipe_slow ); %} -instruct reduction8L(rRegL dst, rRegL src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_LONG && - vector_length(n->in(2)) == 8); // src2 +instruct reductionL_avx512dq(rRegL dst, rRegL src1, vec src2, vec vtmp1, vec vtmp2) %{ + predicate(vector_element_basic_type(n->in(2)) == T_LONG && VM_Version::supports_avx512dq()); match(Set dst (AddReductionVL src1 src2)); match(Set dst (MulReductionVL src1 src2)); match(Set dst (AndReductionV src1 src2)); @@ -4599,9 +4576,8 @@ instruct reduction8D(regD dst, legVec src, legVec vtmp1, legVec vtmp2) %{ // =======================Byte Reduction========================================== #ifdef _LP64 -instruct reductionB(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_BYTE && - vector_length(n->in(2)) <= 32); // src2 +instruct reductionB(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ + predicate(vector_element_basic_type(n->in(2)) == T_BYTE && !VM_Version::supports_avx512bw()); match(Set dst (AddReductionVI src1 src2)); match(Set dst (AndReductionV src1 src2)); match(Set dst ( OrReductionV src1 src2)); @@ -4618,9 +4594,8 @@ instruct reductionB(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtmp2) %{ ins_pipe( pipe_slow ); %} -instruct reduction64B(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_BYTE && - vector_length(n->in(2)) == 64); // src2 +instruct reductionB_avx512bw(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtmp2) %{ + predicate(vector_element_basic_type(n->in(2)) == T_BYTE && VM_Version::supports_avx512bw()); match(Set dst (AddReductionVI src1 src2)); match(Set dst (AndReductionV src1 src2)); match(Set dst ( OrReductionV src1 src2)); @@ -4641,8 +4616,7 @@ instruct reduction64B(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec v // =======================Short Reduction========================================== instruct reductionS(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ - predicate(vector_element_basic_type(n->in(2)) == T_SHORT && - vector_length(n->in(2)) <= 32); // src2 + predicate(vector_element_basic_type(n->in(2)) == T_SHORT); // src2 match(Set dst (AddReductionVI src1 src2)); match(Set dst (MulReductionVI src1 src2)); match(Set dst (AndReductionV src1 src2)); @@ -5472,7 +5446,7 @@ instruct vmulL_mem(vec dst, vec src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct mul2L_reg(vec dst, vec src2, vec tmp) %{ +instruct mul2L_reg(vec dst, vec src2, legVec tmp) %{ predicate(vector_length(n) == 2 && !VM_Version::supports_avx512dq()); match(Set dst (MulVL dst src2)); effect(TEMP dst, TEMP tmp); @@ -5498,7 +5472,7 @@ instruct mul2L_reg(vec dst, vec src2, vec tmp) %{ ins_pipe( pipe_slow ); %} -instruct vmul4L_reg_avx(vec dst, vec src1, vec src2, vec tmp, vec tmp1) %{ +instruct vmul4L_reg_avx(vec dst, vec src1, vec src2, legVec tmp, legVec tmp1) %{ predicate(vector_length(n) == 4 && !VM_Version::supports_avx512dq()); match(Set dst (MulVL src1 src2)); effect(TEMP tmp1, TEMP tmp); diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index d47705880b9..cce4027e016 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -13097,6 +13097,28 @@ instruct cmovLL_mem_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, ins_pipe( pipe_cmov_reg_long ); %} +instruct cmovLL_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegL dst, eRegL src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); + ins_cost(400); + format %{ "CMOV$cmp $dst.lo,$src.lo\n\t" + "CMOV$cmp $dst.hi,$src.hi" %} + opcode(0x0F,0x40); + ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) ); + ins_pipe( pipe_cmov_reg_long ); +%} + +instruct cmovLL_mem_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegL dst, load_long_memory src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src)))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); + ins_cost(500); + format %{ "CMOV$cmp $dst.lo,$src.lo\n\t" + "CMOV$cmp $dst.hi,$src.hi+4" %} + opcode(0x0F,0x40); + ins_encode( enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src) ); + ins_pipe( pipe_cmov_reg_long ); +%} + // Compare 2 longs and CMOVE ints. instruct cmovII_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, rRegI dst, rRegI src) %{ predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 552c345563a..71cc3056a55 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2236,7 +2236,7 @@ bool os::can_execute_large_page_memory() { return false; } -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); char* result = NULL; diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 68196755732..d95cb6807d2 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -1905,7 +1905,7 @@ bool os::can_execute_large_page_memory() { return false; } -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); char* result = pd_attempt_reserve_memory_at(requested_addr, bytes); if (result != NULL) { diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 8536a161e64..c9d07dfb0fe 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4214,7 +4214,7 @@ bool os::can_execute_large_page_memory() { return UseTransparentHugePages || UseHugeTLBFS; } -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); char* result = pd_attempt_reserve_memory_at(requested_addr, bytes); if (result != NULL) { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 3da46a777a1..7298fb21638 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -297,37 +297,18 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in return map_memory_to_file(base, size, fd); } -// Multiple threads can race in this code, and can remap over each other with MAP_FIXED, -// so on posix, unmap the section at the start and at the end of the chunk that we mapped -// rather than unmapping and remapping the whole chunk to get requested alignment. -char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { +static size_t calculate_aligned_extra_size(size_t size, size_t alignment) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); + return extra_size; +} - char* extra_base; - if (file_desc != -1) { - // For file mapping, we do not call os:reserve_memory_with_fd since: - // - we later chop away parts of the mapping using os::release_memory and that could fail if the - // original mmap call had been tied to an fd. - // - The memory API os::reserve_memory uses is an implementation detail. It may (and usually is) - // mmap but it also may System V shared memory which cannot be uncommitted as a whole, so - // chopping off and unmapping excess bits back and front (see below) would not work. - extra_base = reserve_mmapped_memory(extra_size, NULL); - if (extra_base != NULL) { - MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC); - } - } else { - extra_base = os::reserve_memory(extra_size); - } - - if (extra_base == NULL) { - return NULL; - } - +// After a bigger chunk was mapped, unmaps start and end parts to get the requested alignment. +static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base, size_t extra_size) { // Do manual alignment char* aligned_base = align_up(extra_base, alignment); @@ -349,13 +330,39 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { os::release_memory(extra_base + begin_offset + size, end_offset); } - if (file_desc != -1) { - // After we have an aligned address, we can replace anonymous mapping with file mapping - if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) { - vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); - } - MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); + return aligned_base; +} + +// Multiple threads can race in this code, and can remap over each other with MAP_FIXED, +// so on posix, unmap the section at the start and at the end of the chunk that we mapped +// rather than unmapping and remapping the whole chunk to get requested alignment. +char* os::reserve_memory_aligned(size_t size, size_t alignment) { + size_t extra_size = calculate_aligned_extra_size(size, alignment); + char* extra_base = os::reserve_memory(extra_size); + if (extra_base == NULL) { + return NULL; + } + return chop_extra_memory(size, alignment, extra_base, extra_size); +} + +char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_desc) { + size_t extra_size = calculate_aligned_extra_size(size, alignment); + // For file mapping, we do not call os:map_memory_to_file(size,fd) since: + // - we later chop away parts of the mapping using os::release_memory and that could fail if the + // original mmap call had been tied to an fd. + // - The memory API os::reserve_memory uses is an implementation detail. It may (and usually is) + // mmap but it also may System V shared memory which cannot be uncommitted as a whole, so + // chopping off and unmapping excess bits back and front (see below) would not work. + char* extra_base = reserve_mmapped_memory(extra_size, NULL); + if (extra_base == NULL) { + return NULL; + } + char* aligned_base = chop_extra_memory(size, alignment, extra_base, extra_size); + // After we have an aligned address, we can replace anonymous mapping with file mapping + if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); } + MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); return aligned_base; } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 0416605e309..99ac2c074f3 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3137,7 +3137,7 @@ void os::split_reserved_memory(char *base, size_t size, size_t split) { // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); @@ -3148,7 +3148,9 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { char* aligned_base = NULL; do { - char* extra_base = os::reserve_memory_with_fd(extra_size, file_desc); + char* extra_base = file_desc != -1 ? + os::map_memory_to_file(extra_size, file_desc) : + os::reserve_memory(extra_size); if (extra_base == NULL) { return NULL; } @@ -3161,13 +3163,23 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { os::release_memory(extra_base, extra_size); } - aligned_base = os::attempt_reserve_memory_at(aligned_base, size, file_desc); + aligned_base = file_desc != -1 ? + os::attempt_map_memory_to_file_at(aligned_base, size, file_desc) : + os::attempt_reserve_memory_at(aligned_base, size); } while (aligned_base == NULL); return aligned_base; } +char* os::reserve_memory_aligned(size_t size, size_t alignment) { + return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */); +} + +char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd) { + return map_or_reserve_memory_aligned(size, alignment, fd); +} + char* os::pd_reserve_memory(size_t bytes) { return pd_attempt_reserve_memory_at(NULL /* addr */, bytes); } @@ -3205,7 +3217,7 @@ char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes) { return res; } -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); return map_memory_to_file(requested_addr, bytes, file_desc); } diff --git a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp b/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp index f1595ee9e7d..b9ee395bc30 100644 --- a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp +++ b/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp @@ -184,7 +184,9 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, #ifdef M68K return add_using_helper(m68k_add_and_fetch, dest, add_value); #else - return __sync_add_and_fetch(dest, add_value); + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; #endif // M68K #endif // ARM } @@ -196,7 +198,9 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(D volatile* dest, I add_value, STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); - return __sync_add_and_fetch(dest, add_value); + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; } template<> diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index cb85f39dd47..162951c4317 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -86,7 +86,7 @@ int VM_Version::get_current_sve_vector_length() { return prctl(PR_SVE_GET_VL); } -int VM_Version::set_and_get_current_sve_vector_lenght(int length) { +int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(_features & CPU_SVE, "should not call this"); int new_length = prctl(PR_SVE_SET_VL, length); return new_length; diff --git a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp index b44521c1303..e373b90bd9b 100644 --- a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp @@ -49,7 +49,9 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); - return __sync_add_and_fetch(dest, add_value); + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; } template<> @@ -58,7 +60,10 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); - return __sync_add_and_fetch(dest, add_value); + + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; } template<> diff --git a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp index 80270aa62e1..825faddde01 100644 --- a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp @@ -32,7 +32,7 @@ int VM_Version::get_current_sve_vector_length() { return 0; } -int VM_Version::set_and_get_current_sve_vector_lenght(int length) { +int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(_features & CPU_SVE, "should not call this"); ShouldNotReachHere(); return 0; diff --git a/src/hotspot/share/asm/assembler.cpp b/src/hotspot/share/asm/assembler.cpp index 3a0b3ce0b3b..66e3052bdeb 100644 --- a/src/hotspot/share/asm/assembler.cpp +++ b/src/hotspot/share/asm/assembler.cpp @@ -199,19 +199,6 @@ void Label::patch_instructions(MacroAssembler* masm) { continue; } -#ifdef ASSERT - // Cross-section branches only work if the - // intermediate section boundaries are frozen. - if (target_sect != branch_sect) { - for (int n = MIN2(target_sect, branch_sect), - nlimit = (target_sect + branch_sect) - n; - n < nlimit; n++) { - CodeSection* cs = cb->code_section(n); - assert(cs->is_frozen(), "cross-section branch needs stable offsets"); - } - } -#endif //ASSERT - // Push the target offset into the branch instruction. masm->pd_patch_instruction(branch, target, file, line); } diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 558dee23ecc..db2178f9977 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -140,7 +140,7 @@ CodeBuffer::~CodeBuffer() { // Claim is that stack allocation ensures resources are cleaned up. // This is resource clean up, let's hope that all were properly copied out. - free_strings(); + NOT_PRODUCT(free_strings();) #ifdef ASSERT // Save allocation type to execute assert in ~ResourceObj() @@ -176,28 +176,6 @@ void CodeBuffer::initialize_section_size(CodeSection* cs, csize_t size) { if (_insts.has_locs()) cs->initialize_locs(1); } -void CodeBuffer::freeze_section(CodeSection* cs) { - CodeSection* next_cs = (cs == consts())? NULL: code_section(cs->index()+1); - csize_t frozen_size = cs->size(); - if (next_cs != NULL) { - frozen_size = next_cs->align_at_start(frozen_size); - } - address old_limit = cs->limit(); - address new_limit = cs->start() + frozen_size; - relocInfo* old_locs_limit = cs->locs_limit(); - relocInfo* new_locs_limit = cs->locs_end(); - // Patch the limits. - cs->_limit = new_limit; - cs->_locs_limit = new_locs_limit; - cs->_frozen = true; - if (next_cs != NULL && !next_cs->is_allocated() && !next_cs->is_frozen()) { - // Give remaining buffer space to the following section. - next_cs->initialize(new_limit, old_limit - new_limit); - next_cs->initialize_shared_locs(new_locs_limit, - old_locs_limit - new_locs_limit); - } -} - void CodeBuffer::set_blob(BufferBlob* blob) { _blob = blob; if (blob != NULL) { @@ -257,23 +235,19 @@ int CodeBuffer::locator(address addr) const { return -1; } -address CodeBuffer::locator_address(int locator) const { - if (locator < 0) return NULL; - address start = code_section(locator_sect(locator))->start(); - return start + locator_pos(locator); -} bool CodeBuffer::is_backward_branch(Label& L) { return L.is_bound() && insts_end() <= locator_address(L.loc()); } +#ifndef PRODUCT address CodeBuffer::decode_begin() { address begin = _insts.start(); if (_decode_begin != NULL && _decode_begin > begin) begin = _decode_begin; return begin; } - +#endif // !PRODUCT GrowableArray* CodeBuffer::create_patch_overflow() { if (_overflow_arena == NULL) { @@ -505,18 +479,6 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const { } else { guarantee(padding == 0, "In first iteration no padding should be needed."); } - #ifdef ASSERT - if (prev_cs != NULL && prev_cs->is_frozen() && n < (SECT_LIMIT - 1)) { - // Make sure the ends still match up. - // This is important because a branch in a frozen section - // might target code in a following section, via a Label, - // and without a relocation record. See Label::patch_instructions. - address dest_start = buf+buf_offset; - csize_t start2start = cs->start() - prev_cs->start(); - csize_t dest_start2start = dest_start - prev_dest_cs->start(); - assert(start2start == dest_start2start, "cannot stretch frozen sect"); - } - #endif //ASSERT prev_dest_cs = dest_cs; prev_cs = cs; } @@ -752,7 +714,7 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) { relocate_code_to(&dest); // transfer strings and comments from buffer to blob - dest_blob->set_strings(_code_strings); + NOT_PRODUCT(dest_blob->set_strings(_code_strings);) // Done moving code bytes; were they the right size? assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); @@ -895,9 +857,6 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { // Resizing must be allowed { if (blob() == NULL) return; // caller must check for blob == NULL - for (int n = 0; n < (int)SECT_LIMIT; n++) { - guarantee(!code_section(n)->is_frozen(), "resizing not allowed when frozen"); - } } // Figure new capacity for each section. @@ -957,12 +916,11 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size, badCodeHeapFreeVal)); - _decode_begin = NULL; // sanity - // Make certain that the new sections are all snugly inside the new blob. verify_section_allocation(); #ifndef PRODUCT + _decode_begin = NULL; // sanity if (PrintNMethods && (WizardMode || Verbose)) { tty->print("expanded CodeBuffer:"); this->print(); @@ -1032,10 +990,6 @@ void CodeBuffer::log_section_sizes(const char* name) { #ifndef PRODUCT -void CodeSection::decode() { - Disassembler::decode(start(), end()); -} - void CodeBuffer::block_comment(intptr_t offset, const char * comment) { if (_collect_comments) { _code_strings.add_comment(offset, comment); @@ -1054,8 +1008,12 @@ class CodeString: public CHeapObj { CodeString* _prev; intptr_t _offset; + static long allocated_code_strings; + ~CodeString() { assert(_next == NULL && _prev == NULL, "wrong interface for freeing list"); + allocated_code_strings--; + log_trace(codestrings)("Freeing CodeString [%s] (%p)", _string, (void*)_string); os::free((void*)_string); } @@ -1064,12 +1022,14 @@ class CodeString: public CHeapObj { public: CodeString(const char * string, intptr_t offset = -1) : _next(NULL), _prev(NULL), _offset(offset) { + allocated_code_strings++; _string = os::strdup(string, mtCode); + log_trace(codestrings)("Created CodeString [%s] (%p)", _string, (void*)_string); } const char * string() const { return _string; } intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } - CodeString* next() const { return _next; } + CodeString* next() const { return _next; } void set_next(CodeString* next) { _next = next; @@ -1094,6 +1054,10 @@ class CodeString: public CHeapObj { } }; +// For tracing statistics. Will use raw increment/decrement, so it might not be +// exact +long CodeString::allocated_code_strings = 0; + CodeString* CodeStrings::find(intptr_t offset) const { CodeString* a = _strings->first_comment(); while (a != NULL && a->offset() != offset) { @@ -1116,7 +1080,7 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) { CodeString* c = new CodeString(comment, offset); CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset); - if (inspos) { + if (inspos != NULL) { // insert after already existing comments with same offset c->set_next(inspos->next()); inspos->set_next(c); @@ -1130,21 +1094,10 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) { } } -void CodeStrings::assign(CodeStrings& other) { - other.check_valid(); - assert(is_null(), "Cannot assign onto non-empty CodeStrings"); - _strings = other._strings; - _strings_last = other._strings_last; -#ifdef ASSERT - _defunct = false; -#endif - other.set_null_and_invalidate(); -} - // Deep copy of CodeStrings for consistent memory management. -// Only used for actual disassembly so this is cheaper than reference counting -// for the "normal" fastdebug case. void CodeStrings::copy(CodeStrings& other) { + log_debug(codestrings)("Copying %d Codestring(s)", other.count()); + other.check_valid(); check_valid(); assert(is_null(), "Cannot copy onto non-empty CodeStrings"); @@ -1152,7 +1105,11 @@ void CodeStrings::copy(CodeStrings& other) { CodeString** ps = &_strings; CodeString* prev = NULL; while (n != NULL) { - *ps = new CodeString(n->string(),n->offset()); + if (n->is_comment()) { + *ps = new CodeString(n->string(), n->offset()); + } else { + *ps = new CodeString(n->string()); + } (*ps)->_prev = prev; prev = *ps; ps = &((*ps)->_next); @@ -1162,13 +1119,6 @@ void CodeStrings::copy(CodeStrings& other) { const char* CodeStrings::_prefix = " ;; "; // default: can be changed via set_prefix -// Check if any block comments are pending for the given offset. -bool CodeStrings::has_block_comment(intptr_t offset) const { - if (_strings == NULL) return false; - CodeString* c = find(offset); - return c != NULL; -} - void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const { check_valid(); if (_strings != NULL) { @@ -1184,8 +1134,19 @@ void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) con } } -// Also sets isNull() +int CodeStrings::count() const { + int i = 0; + CodeString* s = _strings; + while (s != NULL) { + i++; + s = s->_next; + } + return i; +} + +// Also sets is_null() void CodeStrings::free() { + log_debug(codestrings)("Freeing %d out of approx. %ld CodeString(s), ", count(), CodeString::allocated_code_strings); CodeString* n = _strings; while (n) { // unlink the node from the list saving a pointer to the next @@ -1215,15 +1176,14 @@ const char* CodeStrings::add_string(const char * string) { void CodeBuffer::decode() { ttyLocker ttyl; - Disassembler::decode(decode_begin(), insts_end(), tty); + Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &strings())); _decode_begin = insts_end(); } void CodeSection::print(const char* name) { csize_t locs_size = locs_end() - locs_start(); - tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)%s", - name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity(), - is_frozen()? " [frozen]": ""); + tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)", + name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity()); tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d", name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off()); if (PrintRelocations) { @@ -1246,10 +1206,4 @@ void CodeBuffer::print() { } } -// Directly disassemble code buffer. -void CodeBuffer::decode(address start, address end) { - ttyLocker ttyl; - Disassembler::decode(this, start, end, tty); -} - #endif // PRODUCT diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 6363ea41193..255342cbbd0 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -92,7 +92,6 @@ class CodeSection { relocInfo* _locs_limit; // first byte after relocation information buf address _locs_point; // last relocated position (grows upward) bool _locs_own; // did I allocate the locs myself? - bool _frozen; // no more expansion of this section bool _scratch_emit; // Buffer is used for scratch emit, don't relocate. char _index; // my section number (SECT_INST, etc.) CodeBuffer* _outer; // enclosing CodeBuffer @@ -109,7 +108,6 @@ class CodeSection { _locs_limit = NULL; _locs_point = NULL; _locs_own = false; - _frozen = false; _scratch_emit = false; debug_only(_index = (char)-1); debug_only(_outer = (CodeBuffer*)badAddress); @@ -161,12 +159,10 @@ class CodeSection { address locs_point() const { return _locs_point; } csize_t locs_point_off() const{ return (csize_t)(_locs_point - _start); } csize_t locs_capacity() const { return (csize_t)(_locs_limit - _locs_start); } - csize_t locs_remaining()const { return (csize_t)(_locs_limit - _locs_end); } int index() const { return _index; } bool is_allocated() const { return _start != NULL; } bool is_empty() const { return _start == _end; } - bool is_frozen() const { return _frozen; } bool has_locs() const { return _locs_end != NULL; } // Mark scratch buffer. @@ -184,8 +180,6 @@ class CodeSection { void set_end(address pc) { assert(allocates2(pc), "not in CodeBuffer memory: " INTPTR_FORMAT " <= " INTPTR_FORMAT " <= " INTPTR_FORMAT, p2i(_start), p2i(pc), p2i(_limit)); _end = pc; } void set_mark(address pc) { assert(contains2(pc), "not in codeBuffer"); _mark = pc; } - void set_mark_off(int offset) { assert(contains2(offset+_start),"not in codeBuffer"); - _mark = offset + _start; } void set_mark() { _mark = _end; } void clear_mark() { _mark = NULL; } @@ -259,10 +253,6 @@ class CodeSection { csize_t align_at_start(csize_t off) const { return (csize_t) align_up(off, alignment()); } - // Mark a section frozen. Assign its remaining space to - // the following section. It will never expand after this point. - inline void freeze(); // { _outer->freeze_section(this); } - // Ensure there's enough space left in the current section. // Return true if there was an expansion. bool maybe_expand_to_ensure_remaining(csize_t amount); @@ -284,20 +274,18 @@ class CodeStrings { bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env #endif static const char* _prefix; // defaults to " ;; " -#endif CodeString* find(intptr_t offset) const; CodeString* find_last(intptr_t offset) const; void set_null_and_invalidate() { -#ifndef PRODUCT _strings = NULL; _strings_last = NULL; #ifdef ASSERT _defunct = true; -#endif #endif } +#endif public: CodeStrings() { @@ -310,6 +298,7 @@ class CodeStrings { #endif } +#ifndef PRODUCT bool is_null() { #ifdef ASSERT return _strings == NULL; @@ -318,30 +307,25 @@ class CodeStrings { #endif } - const char* add_string(const char * string) PRODUCT_RETURN_(return NULL;); + const char* add_string(const char * string); - void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN; - bool has_block_comment(intptr_t offset) const; - void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN; - // MOVE strings from other to this; invalidate other. - void assign(CodeStrings& other) PRODUCT_RETURN; + void add_comment(intptr_t offset, const char * comment); + void print_block_comment(outputStream* stream, intptr_t offset) const; + int count() const; // COPY strings from other to this; leave other valid. - void copy(CodeStrings& other) PRODUCT_RETURN; + void copy(CodeStrings& other); // FREE strings; invalidate this. - void free() PRODUCT_RETURN; + void free(); // Guarantee that _strings are used at most once; assign and free invalidate a buffer. inline void check_valid() const { -#ifdef ASSERT assert(!_defunct, "Use of invalid CodeStrings"); -#endif } static void set_prefix(const char *prefix) { -#ifndef PRODUCT _prefix = prefix; -#endif } +#endif // !PRODUCT }; // A CodeBuffer describes a memory space into which assembly @@ -410,8 +394,7 @@ class CodeBuffer: public StackObj { csize_t _total_size; // size in bytes of combined memory buffer OopRecorder* _oop_recorder; - CodeStrings _code_strings; - bool _collect_comments; // Indicate if we need to collect block comments at all. + OopRecorder _default_oop_recorder; // override with initialize_oop_recorder Arena* _overflow_arena; @@ -421,8 +404,12 @@ class CodeBuffer: public StackObj { bool _immutable_PIC; #endif - address _decode_begin; // start address for decode +#ifndef PRODUCT + CodeStrings _code_strings; + bool _collect_comments; // Indicate if we need to collect block comments at all. + address _decode_begin; // start address for decode address decode_begin(); +#endif void initialize_misc(const char * name) { // all pointers other than code_start/end and those inside the sections @@ -431,14 +418,15 @@ class CodeBuffer: public StackObj { _before_expand = NULL; _blob = NULL; _oop_recorder = NULL; - _decode_begin = NULL; _overflow_arena = NULL; - _code_strings = CodeStrings(); _last_insn = NULL; #if INCLUDE_AOT _immutable_PIC = false; #endif +#ifndef PRODUCT + _decode_begin = NULL; + _code_strings = CodeStrings(); // Collect block comments, but restrict collection to cases where a disassembly is output. _collect_comments = ( PrintAssembly || PrintStubCode @@ -447,6 +435,7 @@ class CodeBuffer: public StackObj { || PrintSignatureHandlers || UnlockDiagnosticVMOptions ); +#endif } void initialize(address code_start, csize_t code_size) { @@ -464,8 +453,6 @@ class CodeBuffer: public StackObj { void initialize_section_size(CodeSection* cs, csize_t size); - void freeze_section(CodeSection* cs); - // helper for CodeBuffer::expand() void take_over_code_from(CodeBuffer* cs); @@ -557,7 +544,11 @@ class CodeBuffer: public StackObj { static int locator_sect(int locator) { return locator & sect_mask; } static int locator(int pos, int sect) { return (pos << sect_bits) | sect; } int locator(address addr) const; - address locator_address(int locator) const; + address locator_address(int locator) const { + if (locator < 0) return NULL; + address start = code_section(locator_sect(locator))->start(); + return start + locator_pos(locator); + } // Heuristic for pre-packing the taken/not-taken bit of a predicted branch. bool is_backward_branch(Label& L); @@ -574,10 +565,8 @@ class CodeBuffer: public StackObj { address insts_begin() const { return _insts.start(); } address insts_end() const { return _insts.end(); } void set_insts_end(address end) { _insts.set_end(end); } - address insts_limit() const { return _insts.limit(); } address insts_mark() const { return _insts.mark(); } void set_insts_mark() { _insts.set_mark(); } - void clear_insts_mark() { _insts.clear_mark(); } // is there anything in the buffer other than the current section? bool is_pure() const { return insts_size() == total_content_size(); } @@ -635,35 +624,21 @@ class CodeBuffer: public StackObj { // Override default oop recorder. void initialize_oop_recorder(OopRecorder* r); - OopRecorder* oop_recorder() const { return _oop_recorder; } - CodeStrings& strings() { return _code_strings; } + OopRecorder* oop_recorder() const { return _oop_recorder; } address last_insn() const { return _last_insn; } void set_last_insn(address a) { _last_insn = a; } void clear_last_insn() { set_last_insn(NULL); } +#ifndef PRODUCT + CodeStrings& strings() { return _code_strings; } + void free_strings() { if (!_code_strings.is_null()) { _code_strings.free(); // sets _strings Null as a side-effect. } } - - // Directly disassemble code buffer. - // Print the comment associated with offset on stream, if there is one. - virtual void print_block_comment(outputStream* stream, address block_begin) { -#ifndef PRODUCT - intptr_t offset = (intptr_t)(block_begin - _total_start); // I assume total_start is not correct for all code sections. - _code_strings.print_block_comment(stream, offset); -#endif - } - bool has_block_comment(address block_begin) { -#ifndef PRODUCT - intptr_t offset = (intptr_t)(block_begin - _total_start); // I assume total_start is not correct for all code sections. - return _code_strings.has_block_comment(offset); -#else - return false; #endif - } // Code generation void relocate(address at, RelocationHolder const& rspec, int format = 0) { @@ -688,9 +663,6 @@ class CodeBuffer: public StackObj { } } - // Transform an address from the code in this code buffer to a specified code buffer - address transform_address(const CodeBuffer &cb, address addr) const; - void block_comment(intptr_t offset, const char * comment) PRODUCT_RETURN; const char* code_string(const char* str) PRODUCT_RETURN_(return NULL;); @@ -719,11 +691,6 @@ class CodeBuffer: public StackObj { }; - -inline void CodeSection::freeze() { - _outer->freeze_section(this); -} - inline bool CodeSection::maybe_expand_to_ensure_remaining(csize_t amount) { if (remaining() < amount) { _outer->expand(this, amount); return true; } return false; diff --git a/src/hotspot/share/c1/c1_CFGPrinter.cpp b/src/hotspot/share/c1/c1_CFGPrinter.cpp index 21244d92a18..9cd617d5428 100644 --- a/src/hotspot/share/c1/c1_CFGPrinter.cpp +++ b/src/hotspot/share/c1/c1_CFGPrinter.cpp @@ -325,7 +325,7 @@ void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name for (int i = 0; i < intervals->length(); i++) { if (intervals->at(i) != NULL) { - intervals->at(i)->print_on(output()); + intervals->at(i)->print_on(output(), true); } } diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index dcac52014db..782fa7ada03 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -3212,6 +3212,12 @@ void LinearScan::print_reg_num(outputStream* out, int reg_num) { return; } + LIR_Opr opr = get_operand(reg_num); + assert(opr->is_valid(), "unknown register"); + opr->print(out); +} + +LIR_Opr LinearScan::get_operand(int reg_num) { LIR_Opr opr = LIR_OprFact::illegal(); #ifdef X86 @@ -3231,9 +3237,9 @@ void LinearScan::print_reg_num(outputStream* out, int reg_num) { opr = LIR_OprFact::single_xmm(reg_num - pd_first_xmm_reg); #endif } else { - assert(false, "unknown register"); + // reg_num == -1 or a virtual register, return the illegal operand } - opr->print(out); + return opr; } Interval* LinearScan::find_interval_at(int reg_num) const { @@ -4598,7 +4604,7 @@ bool Interval::intersects_any_children_of(Interval* interval) const { #ifndef PRODUCT -void Interval::print_on(outputStream* out) const { +void Interval::print_on(outputStream* out, bool is_cfg_printer) const { const char* SpillState2Name[] = { "no definition", "no spill store", "one spill store", "store at definition", "start in memory", "no optimization" }; const char* UseKind2Name[] = { "N", "L", "S", "M" }; @@ -4608,18 +4614,29 @@ void Interval::print_on(outputStream* out) const { } else { type_name = type2name(type()); } - out->print("%d %s ", reg_num(), type_name); - if (reg_num() < LIR_OprDesc::vreg_base) { - LinearScan::print_reg_num(out, assigned_reg()); - } else if (assigned_reg() != -1 && (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) { - LinearScan::calc_operand_for_interval(this)->print(out); + + if (is_cfg_printer) { + // Special version for compatibility with C1 Visualizer. + LIR_Opr opr = LinearScan::get_operand(reg_num()); + if (opr->is_valid()) { + out->print("\""); + opr->print(out); + out->print("\" "); + } } else { - // Virtual register that has no assigned register yet. - out->print("[ANY]"); + // Improved output for normal debugging. + if (reg_num() < LIR_OprDesc::vreg_base) { + LinearScan::print_reg_num(out, assigned_reg()); + } else if (assigned_reg() != -1 && (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) { + LinearScan::calc_operand_for_interval(this)->print(out); + } else { + // Virtual register that has no assigned register yet. + out->print("[ANY]"); + } + out->print(" "); } - - out->print(" %d %d ", split_parent()->reg_num(), (register_hint(false) != NULL ? register_hint(false)->reg_num() : -1)); + out->print("%d %d ", split_parent()->reg_num(), (register_hint(false) != NULL ? register_hint(false)->reg_num() : -1)); // print ranges Range* cur = _first; diff --git a/src/hotspot/share/c1/c1_LinearScan.hpp b/src/hotspot/share/c1/c1_LinearScan.hpp index 8d86a0d7836..0249453d9c1 100644 --- a/src/hotspot/share/c1/c1_LinearScan.hpp +++ b/src/hotspot/share/c1/c1_LinearScan.hpp @@ -369,6 +369,7 @@ class LinearScan : public CompilationResourceObj { void print_lir(int level, const char* label, bool hir_valid = true); static void print_reg_num(int reg_num) { print_reg_num(tty, reg_num); } static void print_reg_num(outputStream* out, int reg_num); + static LIR_Opr get_operand(int reg_num); #endif #ifdef ASSERT @@ -633,7 +634,11 @@ class Interval : public CompilationResourceObj { // printing #ifndef PRODUCT void print() const { print_on(tty); } - void print_on(outputStream* out) const; + void print_on(outputStream* out) const { + print_on(out, false); + } + // Special version for compatibility with C1 Visualizer. + void print_on(outputStream* out, bool is_cfg_printer) const; // Used for debugging void print_parent() const; diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 1a95e2efbf0..f4d550460d6 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -761,34 +761,29 @@ Method* ciEnv::lookup_method(ciInstanceKlass* accessor, Symbol* sig, Bytecodes::Code bc, constantTag tag) { - // Accessibility checks are performed in ciEnv::get_method_by_index_impl. - assert(check_klass_accessibility(accessor, holder->get_Klass()), "holder not accessible"); - InstanceKlass* accessor_klass = accessor->get_instanceKlass(); Klass* holder_klass = holder->get_Klass(); - Method* dest_method; - LinkInfo link_info(holder_klass, name, sig, accessor_klass, LinkInfo::AccessCheck::required, LinkInfo::LoaderConstraintCheck::required, tag); + + // Accessibility checks are performed in ciEnv::get_method_by_index_impl. + assert(check_klass_accessibility(accessor, holder_klass), "holder not accessible"); + + LinkInfo link_info(holder_klass, name, sig, accessor_klass, + LinkInfo::AccessCheck::required, + LinkInfo::LoaderConstraintCheck::required, + tag); switch (bc) { - case Bytecodes::_invokestatic: - dest_method = - LinkResolver::resolve_static_call_or_null(link_info); - break; - case Bytecodes::_invokespecial: - dest_method = - LinkResolver::resolve_special_call_or_null(link_info); - break; - case Bytecodes::_invokeinterface: - dest_method = - LinkResolver::linktime_resolve_interface_method_or_null(link_info); - break; - case Bytecodes::_invokevirtual: - dest_method = - LinkResolver::linktime_resolve_virtual_method_or_null(link_info); - break; - default: ShouldNotReachHere(); + case Bytecodes::_invokestatic: + return LinkResolver::resolve_static_call_or_null(link_info); + case Bytecodes::_invokespecial: + return LinkResolver::resolve_special_call_or_null(link_info); + case Bytecodes::_invokeinterface: + return LinkResolver::linktime_resolve_interface_method_or_null(link_info); + case Bytecodes::_invokevirtual: + return LinkResolver::linktime_resolve_virtual_method_or_null(link_info); + default: + fatal("Unhandled bytecode: %s", Bytecodes::name(bc)); + return NULL; // silence compiler warnings } - - return dest_method; } diff --git a/src/hotspot/share/ci/ciMemberName.cpp b/src/hotspot/share/ci/ciMemberName.cpp index 978ba2b975c..4306e6e649e 100644 --- a/src/hotspot/share/ci/ciMemberName.cpp +++ b/src/hotspot/share/ci/ciMemberName.cpp @@ -34,11 +34,6 @@ // Return: MN.vmtarget ciMethod* ciMemberName::get_vmtarget() const { VM_ENTRY_MARK; - // FIXME: Share code with ciMethodHandle::get_vmtarget - Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(get_oop()); - if (vmtarget->is_method()) - return CURRENT_ENV->get_method((Method*) vmtarget); - // FIXME: What if the vmtarget is a Klass? - assert(false, ""); - return NULL; + Method* vmtarget = java_lang_invoke_MemberName::vmtarget(get_oop()); + return CURRENT_ENV->get_method(vmtarget); } diff --git a/src/hotspot/share/ci/ciMethodHandle.cpp b/src/hotspot/share/ci/ciMethodHandle.cpp index be6b76bd49a..49de75353a6 100644 --- a/src/hotspot/share/ci/ciMethodHandle.cpp +++ b/src/hotspot/share/ci/ciMethodHandle.cpp @@ -36,11 +36,6 @@ ciMethod* ciMethodHandle::get_vmtarget() const { VM_ENTRY_MARK; oop form_oop = java_lang_invoke_MethodHandle::form(get_oop()); oop vmentry_oop = java_lang_invoke_LambdaForm::vmentry(form_oop); - // FIXME: Share code with ciMemberName::get_vmtarget - Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(vmentry_oop); - if (vmtarget->is_method()) - return CURRENT_ENV->get_method((Method*) vmtarget); - // FIXME: What if the vmtarget is a Klass? - assert(false, ""); - return NULL; + Method* vmtarget = java_lang_invoke_MemberName::vmtarget(vmentry_oop); + return CURRENT_ENV->get_method(vmtarget); } diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index d5dbf6c3f4d..739a1e7a186 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -3645,12 +3645,6 @@ bool ClassFileParser::supports_sealed_types() { Arguments::enable_preview(); } -bool ClassFileParser::supports_records() { - return _major_version == JVM_CLASSFILE_MAJOR_VERSION && - _minor_version == JAVA_PREVIEW_MINOR_VERSION && - Arguments::enable_preview(); -} - void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs, ConstantPool* cp, ClassFileParser::ClassAnnotationCollector* parsed_annotations, @@ -3898,63 +3892,37 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf "Nest-host class_info_index %u has bad constant type in class file %s", class_info_index, CHECK); _nest_host = class_info_index; - } else if (_major_version >= JAVA_14_VERSION) { - if (tag == vmSymbols::tag_record()) { - // Skip over Record attribute if not supported or if super class is - // not java.lang.Record. - if (supports_records() && - cp->klass_name_at(_super_class_index) == vmSymbols::java_lang_Record()) { - if (parsed_record_attribute) { - classfile_parse_error("Multiple Record attributes in class file %s", THREAD); + + } else if (_major_version >= JAVA_15_VERSION) { + // Check for PermittedSubclasses tag + if (tag == vmSymbols::tag_permitted_subclasses()) { + if (supports_sealed_types()) { + if (parsed_permitted_subclasses_attribute) { + classfile_parse_error("Multiple PermittedSubclasses attributes in class file %s", CHECK); + return; + } + // Classes marked ACC_FINAL cannot have a PermittedSubclasses attribute. + if (_access_flags.is_final()) { + classfile_parse_error("PermittedSubclasses attribute in final class file %s", CHECK); return; } - // Check that class is final and not abstract. - if (!_access_flags.is_final() || _access_flags.is_abstract()) { - classfile_parse_error("Record attribute in non-final or abstract class file %s", THREAD); + parsed_permitted_subclasses_attribute = true; + permitted_subclasses_attribute_start = cfs->current(); + permitted_subclasses_attribute_length = attribute_length; + } + cfs->skip_u1(attribute_length, CHECK); + + } else if (_major_version >= JAVA_16_VERSION) { + if (tag == vmSymbols::tag_record()) { + if (parsed_record_attribute) { + classfile_parse_error("Multiple Record attributes in class file %s", THREAD); return; } parsed_record_attribute = true; record_attribute_start = cfs->current(); record_attribute_length = attribute_length; - } else if (log_is_enabled(Info, class, record)) { - // Log why the Record attribute was ignored. Note that if the - // class file version is JVM_CLASSFILE_MAJOR_VERSION.65535 and - // --enable-preview wasn't specified then a java.lang.UnsupportedClassVersionError - // exception would have been thrown. - ResourceMark rm(THREAD); - if (supports_records()) { - log_info(class, record)( - "Ignoring Record attribute in class %s because super type is not java.lang.Record", - _class_name->as_C_string()); - } else { - log_info(class, record)( - "Ignoring Record attribute in class %s because class file version is not %d.65535", - _class_name->as_C_string(), JVM_CLASSFILE_MAJOR_VERSION); } - } cfs->skip_u1(attribute_length, CHECK); - } else if (_major_version >= JAVA_15_VERSION) { - // Check for PermittedSubclasses tag - if (tag == vmSymbols::tag_permitted_subclasses()) { - if (supports_sealed_types()) { - if (parsed_permitted_subclasses_attribute) { - classfile_parse_error("Multiple PermittedSubclasses attributes in class file %s", THREAD); - return; - } - // Classes marked ACC_FINAL cannot have a PermittedSubclasses attribute. - if (_access_flags.is_final()) { - classfile_parse_error("PermittedSubclasses attribute in final class file %s", THREAD); - return; - } - parsed_permitted_subclasses_attribute = true; - permitted_subclasses_attribute_start = cfs->current(); - permitted_subclasses_attribute_length = attribute_length; - } - cfs->skip_u1(attribute_length, CHECK); - } else { - // Unknown attribute - cfs->skip_u1(attribute_length, CHECK); - } } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -4452,13 +4420,7 @@ void ClassFileParser::check_super_class_access(const InstanceKlass* this_klass, const InstanceKlass* super_ik = InstanceKlass::cast(super); if (super->is_final()) { - ResourceMark rm(THREAD); - Exceptions::fthrow( - THREAD_AND_LOCATION, - vmSymbols::java_lang_VerifyError(), - "class %s cannot inherit from final class %s", - this_klass->external_name(), - super_ik->external_name()); + classfile_icce_error("class %s cannot inherit from final class %s", super_ik, THREAD); return; } @@ -4603,15 +4565,12 @@ static void check_final_method_override(const InstanceKlass* this_klass, TRAPS) if (can_access) { // this class can access super final method and therefore override ResourceMark rm(THREAD); - Exceptions::fthrow(THREAD_AND_LOCATION, - vmSymbols::java_lang_VerifyError(), - "class %s overrides final method %s.%s%s", - this_klass->external_name(), - super_m->method_holder()->external_name(), - name->as_C_string(), - signature->as_C_string() - ); - return; + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), + err_msg("class %s overrides final method %s.%s%s", + this_klass->external_name(), + super_m->method_holder()->external_name(), + name->as_C_string(), + signature->as_C_string())); } } diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index b617a66c17b..2cd54604d5b 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1179,19 +1179,24 @@ InstanceKlass* SystemDictionaryShared::acquire_class_for_current_thread( return shared_klass; } -static ResourceHashtable< +class LoadedUnregisteredClassesTable : public ResourceHashtable< Symbol*, bool, primitive_hash, primitive_equals, 6661, // prime number - ResourceObj::C_HEAP> _loaded_unregistered_classes; + ResourceObj::C_HEAP> {}; + +static LoadedUnregisteredClassesTable* _loaded_unregistered_classes = NULL; bool SystemDictionaryShared::add_unregistered_class(InstanceKlass* k, TRAPS) { // We don't allow duplicated unregistered classes of the same name. assert(DumpSharedSpaces, "only when dumping"); Symbol* name = k->name(); + if (_loaded_unregistered_classes == NULL) { + _loaded_unregistered_classes = new (ResourceObj::C_HEAP, mtClass)LoadedUnregisteredClassesTable(); + } bool created = false; - _loaded_unregistered_classes.put_if_absent(name, true, &created); + _loaded_unregistered_classes->put_if_absent(name, true, &created); if (created) { MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this. SystemDictionary::add_to_hierarchy(k, CHECK_false); diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index c86927f57b3..df2737f743f 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -147,6 +147,7 @@ \ /* Java runtime version access */ \ template(java_lang_VersionProps, "java/lang/VersionProps") \ + template(java_version_name, "java_version") \ template(java_runtime_name_name, "java_runtime_name") \ template(java_runtime_version_name, "java_runtime_version") \ template(java_runtime_vendor_version_name, "VENDOR_VERSION") \ diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index 18722ac288d..42a4fc0f769 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -87,8 +87,8 @@ CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& la _relocation_end(layout.relocation_end()), _oop_maps(oop_maps), _caller_must_gc_arguments(caller_must_gc_arguments), - _strings(CodeStrings()), _name(name) + NOT_PRODUCT(COMMA _strings(CodeStrings())) { assert(is_aligned(layout.size(), oopSize), "unaligned size"); assert(is_aligned(layout.header_size(), oopSize), "unaligned size"); @@ -115,8 +115,8 @@ CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& la _relocation_begin(layout.relocation_begin()), _relocation_end(layout.relocation_end()), _caller_must_gc_arguments(caller_must_gc_arguments), - _strings(CodeStrings()), _name(name) + NOT_PRODUCT(COMMA _strings(CodeStrings())) { assert(is_aligned(_size, oopSize), "unaligned size"); assert(is_aligned(_header_size, oopSize), "unaligned size"); @@ -158,7 +158,7 @@ RuntimeBlob::RuntimeBlob( void CodeBlob::flush() { FREE_C_HEAP_ARRAY(unsigned char, _oop_maps); _oop_maps = NULL; - _strings.free(); + NOT_PRODUCT(_strings.free();) } void CodeBlob::set_oop_maps(OopMapSet* p) { diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index f8c45e92f95..d9bd003a52d 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -110,10 +110,12 @@ class CodeBlob { ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob bool _caller_must_gc_arguments; - CodeStrings _strings; + const char* _name; S390_ONLY(int _ctable_offset;) + NOT_PRODUCT(CodeStrings _strings;) + CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments); CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments); @@ -231,29 +233,20 @@ class CodeBlob { void dump_for_addr(address addr, outputStream* st, bool verbose) const; void print_code(); - bool has_block_comment(address block_begin) const { - intptr_t offset = (intptr_t)(block_begin - code_begin()); - return _strings.has_block_comment(offset); - } // Print the comment associated with offset on stream, if there is one virtual void print_block_comment(outputStream* stream, address block_begin) const { + #ifndef PRODUCT intptr_t offset = (intptr_t)(block_begin - code_begin()); _strings.print_block_comment(stream, offset); + #endif } - // Transfer ownership of comments to this CodeBlob +#ifndef PRODUCT void set_strings(CodeStrings& strings) { assert(!is_aot(), "invalid on aot"); - _strings.assign(strings); - } - - static ByteSize name_field_offset() { - return byte_offset_of(CodeBlob, _name); - } - - static ByteSize oop_maps_field_offset() { - return byte_offset_of(CodeBlob, _oop_maps); + _strings.copy(strings); } +#endif }; class CodeBlobLayout : public StackObj { diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 92b1e72aef8..6bc04b44045 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -695,9 +695,7 @@ class nmethod : public CompiledMethod { CodeBlob::print_block_comment(stream, block_begin); #endif } - bool has_block_comment(address block_begin) { - return CodeBlob::has_block_comment(block_begin); - } + void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const; const char* nmethod_section_label(address pos) const; diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index b940a7e8e36..753f9798a83 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -322,7 +322,6 @@ class DirectiveSetPtr { // - if some option is changed we need to copy directiveset since it no longer can be shared // - Need to free copy after use // - Requires a modified bit so we don't overwrite options that is set by directives - DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) { // Early bail out - checking all options is expensive - we rely on them not being used // Only set a flag if it has not been modified and value changes. @@ -360,6 +359,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle } // inline and dontinline (including exclude) are implemented in the directiveset accessors + // ignore flags whose cc_flags are X #define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } } compilerdirectives_common_flags(init_default_cc) compilerdirectives_c2_flags(init_default_cc) diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index a04c13ea061..a67e534a9b2 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -36,8 +36,8 @@ #define compilerdirectives_common_flags(cflags) \ cflags(Enable, bool, false, X) \ cflags(Exclude, bool, false, X) \ - cflags(BreakAtExecute, bool, false, X) \ - cflags(BreakAtCompile, bool, false, X) \ + cflags(BreakAtExecute, bool, false, BreakAtExecute) \ + cflags(BreakAtCompile, bool, false, BreakAtCompile) \ cflags(Log, bool, LogCompilation, X) \ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \ diff --git a/src/hotspot/share/compiler/disassembler.cpp b/src/hotspot/share/compiler/disassembler.cpp index fe36206ddd0..61f0b23575f 100644 --- a/src/hotspot/share/compiler/disassembler.cpp +++ b/src/hotspot/share/compiler/disassembler.cpp @@ -48,12 +48,9 @@ bool Disassembler::_library_usable = false; // This routine is in the shared library: Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL; -Disassembler::decode_func Disassembler::_decode_instructions = NULL; static const char hsdis_library_name[] = "hsdis-" HOTSPOT_LIB_ARCH; static const char decode_instructions_virtual_name[] = "decode_instructions_virtual"; -static const char decode_instructions_name[] = "decode_instructions"; -static bool use_new_version = true; #define COMMENT_COLUMN 52 LP64_ONLY(+8) /*could be an option*/ #define BYTES_COMMENT ";..." /* funky byte display comment */ @@ -63,7 +60,7 @@ class decode_env { CodeBuffer* _codeBuffer; // != NULL only when decoding a CodeBuffer CodeBlob* _codeBlob; // != NULL only when decoding a CodeBlob nmethod* _nm; // != NULL only when decoding a nmethod - CodeStrings _strings; + address _start; // != NULL when decoding a range of unknown type address _end; // != NULL when decoding a range of unknown type @@ -77,6 +74,7 @@ class decode_env { bool _print_help; bool _helpPrinted; static bool _optionsParsed; + NOT_PRODUCT(const CodeStrings* _strings;) enum { tabspacing = 8 @@ -214,12 +212,11 @@ class decode_env { } public: - decode_env(CodeBuffer* code, outputStream* output); - decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings() /* , ptrdiff_t offset */); - decode_env(nmethod* code, outputStream* output, CodeStrings c = CodeStrings()); + decode_env(CodeBlob* code, outputStream* output); + decode_env(nmethod* code, outputStream* output); // Constructor for a 'decode_env' to decode an arbitrary // piece of memory, hopefully containing code. - decode_env(address start, address end, outputStream* output); + decode_env(address start, address end, outputStream* output, const CodeStrings* strings = NULL); // Add 'original_start' argument which is the the original address // the instructions were located at (if this is not equal to 'start'). @@ -322,34 +319,10 @@ void decode_env::print_hook_comments(address pc, bool newline) { } } -decode_env::decode_env(CodeBuffer* code, outputStream* output) : - _output(output ? output : tty), - _codeBuffer(code), - _codeBlob(NULL), - _nm(NULL), - _strings(), - _start(NULL), - _end(NULL), - _option_buf(), - _print_raw(0), - _cur_insn(NULL), - _bytes_per_line(0), - _pre_decode_alignment(0), - _post_decode_alignment(0), - _print_file_name(false), - _print_help(false), - _helpPrinted(false) { - - memset(_option_buf, 0, sizeof(_option_buf)); - process_options(_output); -} - -decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) : +decode_env::decode_env(CodeBlob* code, outputStream* output) : _output(output ? output : tty), - _codeBuffer(NULL), _codeBlob(code), _nm(_codeBlob != NULL && _codeBlob->is_nmethod() ? (nmethod*) code : NULL), - _strings(), _start(NULL), _end(NULL), _option_buf(), @@ -360,19 +333,18 @@ decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) : _post_decode_alignment(0), _print_file_name(false), _print_help(false), - _helpPrinted(false) { + _helpPrinted(false) + NOT_PRODUCT(COMMA _strings(NULL)) { memset(_option_buf, 0, sizeof(_option_buf)); - _strings.copy(c); process_options(_output); + } -decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) : +decode_env::decode_env(nmethod* code, outputStream* output) : _output(output ? output : tty), - _codeBuffer(NULL), _codeBlob(NULL), _nm(code), - _strings(), _start(_nm->code_begin()), _end(_nm->code_end()), _option_buf(), @@ -383,21 +355,19 @@ decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) : _post_decode_alignment(0), _print_file_name(false), _print_help(false), - _helpPrinted(false) { + _helpPrinted(false) + NOT_PRODUCT(COMMA _strings(NULL)) { memset(_option_buf, 0, sizeof(_option_buf)); - _strings.copy(c); process_options(_output); } // Constructor for a 'decode_env' to decode a memory range [start, end) // of unknown origin, assuming it contains code. -decode_env::decode_env(address start, address end, outputStream* output) : +decode_env::decode_env(address start, address end, outputStream* output, const CodeStrings* c) : _output(output ? output : tty), - _codeBuffer(NULL), _codeBlob(NULL), _nm(NULL), - _strings(), _start(start), _end(end), _option_buf(), @@ -408,7 +378,8 @@ decode_env::decode_env(address start, address end, outputStream* output) : _post_decode_alignment(0), _print_file_name(false), _print_help(false), - _helpPrinted(false) { + _helpPrinted(false) + NOT_PRODUCT(COMMA _strings(c)) { assert(start < end, "Range must have a positive size, [" PTR_FORMAT ".." PTR_FORMAT ").", p2i(start), p2i(end)); memset(_option_buf, 0, sizeof(_option_buf)); @@ -682,10 +653,11 @@ void decode_env::print_insn_labels() { if (_codeBlob != NULL) { _codeBlob->print_block_comment(st, p); } - if (_codeBuffer != NULL) { - _codeBuffer->print_block_comment(st, p); +#ifndef PRODUCT + if (_strings != NULL) { + _strings->print_block_comment(st, (intptr_t)(p - _start)); } - _strings.print_block_comment(st, (intptr_t)(p - _start)); +#endif } } @@ -761,34 +733,22 @@ address decode_env::decode_instructions(address start, address end, address orig // This is mainly for debugging the library itself. FILE* out = stdout; FILE* xmlout = (_print_raw > 1 ? out : NULL); - return use_new_version ? + return (address) (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end, start, end - start, NULL, (void*) xmlout, NULL, (void*) out, - options(), 0/*nice new line*/) - : - (address) - (*Disassembler::_decode_instructions)(start, end, - NULL, (void*) xmlout, - NULL, (void*) out, - options()); + options(), 0/*nice new line*/); } - return use_new_version ? + return (address) (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end, start, end - start, &event_to_env, (void*) this, &printf_to_env, (void*) this, - options(), 0/*nice new line*/) - : - (address) - (*Disassembler::_decode_instructions)(start, end, - &event_to_env, (void*) this, - &printf_to_env, (void*) this, - options()); + options(), 0/*nice new line*/); } // ---------------------------------------------------------------------------- @@ -878,21 +838,13 @@ bool Disassembler::load_library(outputStream* st) { _library = os::dll_load(buf, ebuf, sizeof ebuf); } - // load the decoder function to use (new or old version). + // load the decoder function to use. if (_library != NULL) { _decode_instructions_virtual = CAST_TO_FN_PTR(Disassembler::decode_func_virtual, os::dll_lookup(_library, decode_instructions_virtual_name)); } - if (_decode_instructions_virtual == NULL && _library != NULL) { - // could not spot in new version, try old version - _decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func, - os::dll_lookup(_library, decode_instructions_name)); - use_new_version = false; - } else { - use_new_version = true; - } _tried_to_load_library = true; - _library_usable = _decode_instructions_virtual != NULL || _decode_instructions != NULL; + _library_usable = _decode_instructions_virtual != NULL; // Create a dummy environment to initialize PrintAssemblyOptions. // The PrintAssemblyOptions must be known for abstract disassemblies as well. @@ -919,49 +871,13 @@ bool Disassembler::load_library(outputStream* st) { } -// Directly disassemble code buffer. -void Disassembler::decode(CodeBuffer* cb, address start, address end, outputStream* st) { -#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) - //---< Test memory before decoding >--- - if (!(cb->contains(start) && cb->contains(end))) { - //---< Allow output suppression, but prevent writing to a NULL stream. Could happen with +PrintStubCode. >--- - if (st != NULL) { - st->print("Memory range [" PTR_FORMAT ".." PTR_FORMAT "] not contained in CodeBuffer", p2i(start), p2i(end)); - } - return; - } - if (!os::is_readable_range(start, end)) { - //---< Allow output suppression, but prevent writing to a NULL stream. Could happen with +PrintStubCode. >--- - if (st != NULL) { - st->print("Memory range [" PTR_FORMAT ".." PTR_FORMAT "] not readable", p2i(start), p2i(end)); - } - return; - } - - decode_env env(cb, st); - env.output()->print_cr("--------------------------------------------------------------------------------"); - env.output()->print("Decoding CodeBuffer (" PTR_FORMAT ")", p2i(cb)); - if (cb->name() != NULL) { - env.output()->print(", name: %s,", cb->name()); - } - env.output()->print_cr(" at [" PTR_FORMAT ", " PTR_FORMAT "] " JLONG_FORMAT " bytes", p2i(start), p2i(end), ((jlong)(end - start))); - - if (is_abstract()) { - AbstractDisassembler::decode_abstract(start, end, env.output(), Assembler::instr_maxlen()); - } else { - env.decode_instructions(start, end); - } - env.output()->print_cr("--------------------------------------------------------------------------------"); -#endif -} - // Directly disassemble code blob. -void Disassembler::decode(CodeBlob* cb, outputStream* st, CodeStrings c) { +void Disassembler::decode(CodeBlob* cb, outputStream* st) { #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) if (cb->is_nmethod()) { // If we have an nmethod at hand, // call the specialized decoder directly. - decode((nmethod*)cb, st, c); + decode((nmethod*)cb, st); return; } @@ -999,7 +915,7 @@ void Disassembler::decode(CodeBlob* cb, outputStream* st, CodeStrings c) { // Decode a nmethod. // This includes printing the constant pool and all code segments. // The nmethod data structures (oop maps, relocations and the like) are not printed. -void Disassembler::decode(nmethod* nm, outputStream* st, CodeStrings c) { +void Disassembler::decode(nmethod* nm, outputStream* st) { #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) ttyLocker ttyl; @@ -1018,7 +934,7 @@ void Disassembler::decode(nmethod* nm, outputStream* st, CodeStrings c) { } // Decode a range, given as [start address, end address) -void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c /*, ptrdiff_t offset */) { +void Disassembler::decode(address start, address end, outputStream* st, const CodeStrings* c) { #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) //---< Test memory before decoding >--- if (!os::is_readable_range(start, end)) { @@ -1046,7 +962,7 @@ void Disassembler::decode(address start, address end, outputStream* st, CodeStri #endif { // This seems to be just a chunk of memory. - decode_env env(start, end, st); + decode_env env(start, end, st, c); env.output()->print_cr("--------------------------------------------------------------------------------"); env.decode_instructions(start, end); env.output()->print_cr("--------------------------------------------------------------------------------"); diff --git a/src/hotspot/share/compiler/disassembler.hpp b/src/hotspot/share/compiler/disassembler.hpp index 523b423d9c2..93228a565b4 100644 --- a/src/hotspot/share/compiler/disassembler.hpp +++ b/src/hotspot/share/compiler/disassembler.hpp @@ -28,7 +28,8 @@ #include "utilities/globalDefinitions.hpp" #include "asm/assembler.hpp" -#include "asm/codeBuffer.hpp" +#include "code/codeBlob.hpp" +#include "code/nmethod.hpp" #include "compiler/abstractDisassembler.hpp" #include "runtime/globals.hpp" #include "utilities/macros.hpp" @@ -51,13 +52,6 @@ class Disassembler : public AbstractDisassembler { void* printf_stream, const char* options, int newline); - // this is the type of the dll entry point for old version: - typedef void* (*decode_func)(void* start_va, void* end_va, - void* (*event_callback)(void*, const char*, void*), - void* event_stream, - int (*printf_callback)(void*, const char*, ...), - void* printf_stream, - const char* options); // points to the library. static void* _library; // bailout @@ -65,7 +59,6 @@ class Disassembler : public AbstractDisassembler { static bool _library_usable; // points to the decode function. static decode_func_virtual _decode_instructions_virtual; - static decode_func _decode_instructions; // tries to load library and return whether it succeeded. // Allow (diagnostic) output redirection. @@ -88,10 +81,10 @@ class Disassembler : public AbstractDisassembler { // about which decoding format is used. // We can also enforce using the abstract disassembler. static bool is_abstract() { - if (!_tried_to_load_library /* && !UseAbstractDisassembler */) { + if (!_tried_to_load_library) { load_library(); } - return ! _library_usable /* || UseAbstractDisassembler */; // Not available until DecodeErrorFile is supported. + return ! _library_usable; } // Check out if we are doing a live disassembly or a post-mortem @@ -105,14 +98,12 @@ class Disassembler : public AbstractDisassembler { #endif } - // Directly disassemble code buffer. - static void decode(CodeBuffer* cb, address start, address end, outputStream* st = NULL); // Directly disassemble code blob. - static void decode(CodeBlob *cb, outputStream* st = NULL, CodeStrings c = CodeStrings()); + static void decode(CodeBlob *cb, outputStream* st = NULL); // Directly disassemble nmethod. - static void decode(nmethod* nm, outputStream* st = NULL, CodeStrings c = CodeStrings()); + static void decode(nmethod* nm, outputStream* st = NULL); // Disassemble an arbitrary memory range. - static void decode(address start, address end, outputStream* st = NULL, CodeStrings c = CodeStrings() /* , ptrdiff_t offset */); + static void decode(address start, address end, outputStream* st = NULL, const CodeStrings* = NULL); static void _hook(const char* file, int line, class MacroAssembler* masm); diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index cb172b5f5b5..c20b4400cad 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -281,22 +281,9 @@ HeapWord* G1Allocator::old_attempt_allocation(size_t min_word_size, return result; } -uint G1PLABAllocator::calc_survivor_alignment_bytes() { - assert(SurvivorAlignmentInBytes >= ObjectAlignmentInBytes, "sanity"); - if (SurvivorAlignmentInBytes == ObjectAlignmentInBytes) { - // No need to align objects in the survivors differently, return 0 - // which means "survivor alignment is not used". - return 0; - } else { - assert(SurvivorAlignmentInBytes > 0, "sanity"); - return SurvivorAlignmentInBytes; - } -} - G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) : _g1h(G1CollectedHeap::heap()), - _allocator(allocator), - _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { + _allocator(allocator) { for (region_type_t state = 0; state < G1HeapRegionAttr::Num; state++) { _direct_allocated[state] = 0; uint length = alloc_buffers_length(state); diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index f0702b4d6c2..4346171466f 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -149,13 +149,6 @@ class G1PLABAllocator : public CHeapObj { PLAB** _alloc_buffers[G1HeapRegionAttr::Num]; - // The survivor alignment in effect in bytes. - // == 0 : don't align survivors - // != 0 : align survivors to that alignment - // These values were chosen to favor the non-alignment case since some - // architectures have a special compare against zero instructions. - const uint _survivor_alignment_bytes; - // Number of words allocated directly (not counting PLAB allocation). size_t _direct_allocated[G1HeapRegionAttr::Num]; @@ -168,10 +161,6 @@ class G1PLABAllocator : public CHeapObj { // active NUMA nodes. inline uint alloc_buffers_length(region_type_t dest) const; - // Calculate the survivor space object alignment in bytes. Returns that or 0 if - // there are no restrictions on survivor alignment. - static uint calc_survivor_alignment_bytes(); - bool may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const; public: G1PLABAllocator(G1Allocator* allocator); diff --git a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp index 5b6ab355c4d..6d484292051 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp @@ -105,11 +105,7 @@ inline HeapWord* G1PLABAllocator::plab_allocate(G1HeapRegionAttr dest, size_t word_sz, uint node_index) { PLAB* buffer = alloc_buffer(dest, node_index); - if (_survivor_alignment_bytes == 0 || !dest.is_young()) { - return buffer->allocate(word_sz); - } else { - return buffer->allocate_aligned(word_sz, _survivor_alignment_bytes); - } + return buffer->allocate(word_sz); } inline HeapWord* G1PLABAllocator::allocate(G1HeapRegionAttr dest, diff --git a/src/hotspot/share/gc/g1/g1BiasedArray.cpp b/src/hotspot/share/gc/g1/g1BiasedArray.cpp index 0d9a3caf4eb..ce0196ee5bb 100644 --- a/src/hotspot/share/gc/g1/g1BiasedArray.cpp +++ b/src/hotspot/share/gc/g1/g1BiasedArray.cpp @@ -26,11 +26,23 @@ #include "gc/g1/g1BiasedArray.hpp" #include "memory/padded.inline.hpp" +G1BiasedMappedArrayBase::G1BiasedMappedArrayBase() : + _alloc_base(NULL), + _base(NULL), + _length(0), + _biased_base(NULL), + _bias(0), + _shift_by(0) { } + +G1BiasedMappedArrayBase::~G1BiasedMappedArrayBase() { + FreeHeap(_alloc_base); +} + // Allocate a new array, generic version. address G1BiasedMappedArrayBase::create_new_base_array(size_t length, size_t elem_size) { assert(length > 0, "just checking"); assert(elem_size > 0, "just checking"); - return PaddedPrimitiveArray::create_unfreeable(length * elem_size); + return PaddedPrimitiveArray::create(length * elem_size, &_alloc_base); } #ifndef PRODUCT diff --git a/src/hotspot/share/gc/g1/g1BiasedArray.hpp b/src/hotspot/share/gc/g1/g1BiasedArray.hpp index 248abbabf1e..7c604706566 100644 --- a/src/hotspot/share/gc/g1/g1BiasedArray.hpp +++ b/src/hotspot/share/gc/g1/g1BiasedArray.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_G1_G1BIASEDARRAY_HPP #define SHARE_GC_G1_G1BIASEDARRAY_HPP +#include "memory/allocation.hpp" #include "memory/memRegion.hpp" #include "utilities/debug.hpp" #include "utilities/powerOfTwo.hpp" @@ -32,10 +33,14 @@ // Implements the common base functionality for arrays that contain provisions // for accessing its elements using a biased index. // The element type is defined by the instantiating the template. -class G1BiasedMappedArrayBase { +class G1BiasedMappedArrayBase : public CHeapObj { friend class VMStructs; + + void* _alloc_base; // the address the unpadded array has been allocated to + public: typedef size_t idx_t; + protected: address _base; // the real base address size_t _length; // the length of the array @@ -44,12 +49,10 @@ class G1BiasedMappedArrayBase { uint _shift_by; // the amount of bits to shift right when mapping to an index of the array. protected: - - G1BiasedMappedArrayBase() : _base(NULL), _length(0), _biased_base(NULL), - _bias(0), _shift_by(0) { } + G1BiasedMappedArrayBase(); // Allocate a new array, generic version. - static address create_new_base_array(size_t length, size_t elem_size); + address create_new_base_array(size_t length, size_t elem_size); // Initialize the members of this class. The biased start address of this array // is the bias (in elements) multiplied by the element size. @@ -90,8 +93,10 @@ class G1BiasedMappedArrayBase { void verify_biased_index_inclusive_end(idx_t biased_index) const PRODUCT_RETURN; public: - // Return the length of the array in elements. - size_t length() const { return _length; } + virtual ~G1BiasedMappedArrayBase(); + + // Return the length of the array in elements. + size_t length() const { return _length; } }; // Array that provides biased access and mapping from (valid) addresses in the diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index 9f489c0b8bc..277c9e38228 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -60,7 +60,7 @@ void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { assert((index) < (_reserved.word_size() >> BOTConstants::LogN_words), "%s - index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, msg, (index), (_reserved.word_size() >> BOTConstants::LogN_words)); - assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)), + assert(G1CollectedHeap::heap()->is_in(address_for_index_raw(index)), "Index " SIZE_FORMAT " corresponding to " PTR_FORMAT " (%u) is not in committed area.", (index), diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 4e90105b0df..d4400135b92 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2260,29 +2260,9 @@ bool G1CollectedHeap::try_collect(GCCause::Cause cause) { } bool G1CollectedHeap::is_in(const void* p) const { - if (_hrm->reserved().contains(p)) { - // Given that we know that p is in the reserved space, - // heap_region_containing() should successfully - // return the containing region. - HeapRegion* hr = heap_region_containing(p); - return hr->is_in(p); - } else { - return false; - } + return is_in_reserved(p) && _hrm->is_available(addr_to_region((HeapWord*)p)); } -#ifdef ASSERT -bool G1CollectedHeap::is_in_exact(const void* p) const { - bool contains = reserved().contains(p); - bool available = _hrm->is_available(addr_to_region((HeapWord*)p)); - if (contains && available) { - return true; - } else { - return false; - } -} -#endif - // Iteration functions. // Iterates an ObjectClosure over all objects within a HeapRegion. diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 4c98d5f38d9..83f982f7c86 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1136,11 +1136,6 @@ class G1CollectedHeap : public CollectedHeap { void decrement_summary_bytes(size_t bytes); virtual bool is_in(const void* p) const; -#ifdef ASSERT - // Returns whether p is in one of the available areas of the heap. Slow but - // extensive version. - bool is_in_exact(const void* p) const; -#endif // Return "TRUE" iff the given object address is within the collection // set. Assumes that the reference points into the heap. diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp index 4b8d04f4932..a2b0ce26b04 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp @@ -51,7 +51,7 @@ void G1CMBitMap::clear_region(HeapRegion* region) { #ifdef ASSERT void G1CMBitMap::check_mark(HeapWord* addr) { - assert(G1CollectedHeap::heap()->is_in_exact(addr), + assert(G1CollectedHeap::heap()->is_in(addr), "Trying to access bitmap " PTR_FORMAT " for address " PTR_FORMAT " not in the heap.", p2i(this), p2i(addr)); } diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp index 88907a6f87f..69e0778a904 100644 --- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp +++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp @@ -220,7 +220,7 @@ static bool map_nvdimm_space(ReservedSpace rs) { return false; } // commit this memory in nv-dimm - char* ret = os::attempt_reserve_memory_at(rs.base(), rs.size(), _backing_fd); + char* ret = os::attempt_map_memory_to_file_at(rs.base(), rs.size(), _backing_fd); if (ret != rs.base()) { if (ret != NULL) { diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 0284f0b9ccc..a6a55984db8 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1304,7 +1304,7 @@ void G1RemSet::cleanup_after_scan_heap_roots() { inline void check_card_ptr(CardTable::CardValue* card_ptr, G1CardTable* ct) { #ifdef ASSERT G1CollectedHeap* g1h = G1CollectedHeap::heap(); - assert(g1h->is_in_exact(ct->addr_for(card_ptr)), + assert(g1h->is_in(ct->addr_for(card_ptr)), "Card at " PTR_FORMAT " index " SIZE_FORMAT " representing heap at " PTR_FORMAT " (%u) must be in committed heap", p2i(card_ptr), ct->index_for(ct->addr_for(card_ptr)), diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index eadde715f6f..b901ceb15fd 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -516,9 +516,6 @@ class G1VerificationClosure : public BasicOopIterateClosure { obj->print_on(out); #endif // PRODUCT } - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) }; class VerifyLiveClosure : public G1VerificationClosure { @@ -655,9 +652,6 @@ class G1Mux2Closure : public BasicOopIterateClosure { } virtual inline void do_oop(oop* p) { do_oop_work(p); } virtual inline void do_oop(narrowOop* p) { do_oop_work(p); } - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) }; void HeapRegion::verify(VerifyOption vo, diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp index 979db9e2870..48b9875672f 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp @@ -47,9 +47,6 @@ class PCMarkAndPushClosure: public OopClosure { template void do_oop_nv(T* p) { _compaction_manager->mark_and_push(p); } virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) }; class PCIterateMarkAndPushClosure: public MetadataVisitingOopIterateClosure { @@ -64,9 +61,6 @@ class PCIterateMarkAndPushClosure: public MetadataVisitingOopIterateClosure { void do_klass_nv(Klass* k) { _compaction_manager->follow_klass(k); } void do_cld_nv(ClassLoaderData* cld) { _compaction_manager->follow_class_loader(cld); } - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) }; inline bool ParCompactionManager::steal(int queue_num, oop& t) { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp index df4f1c41cda..688da81e9c2 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp @@ -134,8 +134,6 @@ class PCAdjustPointerClosure: public BasicOopIterateClosure { virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } private: ParCompactionManager* _cm; diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp index 1c883058310..b852324e877 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp @@ -32,20 +32,14 @@ HeapWord* PSYoungPromotionLAB::allocate(size_t size) { // Can't assert this, when young fills, we keep the LAB around, but flushed. // assert(_state != flushed, "Sanity"); - HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end(), SurvivorAlignmentInBytes); - if (obj == NULL) { - return NULL; - } - + HeapWord* obj = top(); HeapWord* new_top = obj + size; // The 'new_top>obj' check is needed to detect overflow of obj+size. if (new_top > obj && new_top <= end()) { set_top(new_top); - assert(is_aligned(obj, SurvivorAlignmentInBytes) && is_object_aligned(new_top), - "checking alignment"); + assert(is_object_aligned(new_top), "checking alignment"); return obj; } else { - set_top(obj); return NULL; } } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index 3dc587da9e0..d97694466d5 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -97,9 +97,6 @@ class PSPushContentsClosure: public BasicOopIterateClosure { virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } - - // Don't use the oop verification code in the oop_oop_iterate framework. - debug_only(virtual bool should_verify_oops() { return false; }) }; // diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 2fe070f7ee4..296415542ad 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -711,7 +711,7 @@ oop DefNewGeneration::copy_to_survivor_space(oop old) { // Try allocating obj in to-space (unless too old) if (old->age() < tenuring_threshold()) { - obj = (oop) to()->allocate_aligned(s); + obj = (oop) to()->allocate(s); } // Otherwise try allocating obj tenured diff --git a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp index 744d03c088d..67dce43e7b6 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp @@ -45,7 +45,7 @@ inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) { } #endif // ASSERT - Devirtualizer::do_oop_no_verify(_cl, p); + Devirtualizer::do_oop(_cl, p); // Card marking is trickier for weak refs. // This oop is a 'next' field which was filled in while we @@ -77,7 +77,7 @@ inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) { } #endif // ASSERT - Devirtualizer::do_oop_no_verify(_cl, p); + Devirtualizer::do_oop(_cl, p); // Optimized for Defnew generation if it's the youngest generation: // we set a younger_gen card if we have an older->youngest diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp index 58a4128d8cf..e09d7d06833 100644 --- a/src/hotspot/share/gc/serial/markSweep.hpp +++ b/src/hotspot/share/gc/serial/markSweep.hpp @@ -191,9 +191,6 @@ class AdjustPointerClosure: public BasicOopIterateClosure { virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) }; class PreservedMark { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index e46ecc3dcf4..5df7ad7badb 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -310,12 +310,6 @@ class CollectedHeap : public CHeapObj { virtual size_t min_dummy_object_size() const; size_t tlab_alloc_reserve() const; - // Return the address "addr" aligned by "alignment_in_bytes" if such - // an address is below "end". Return NULL otherwise. - inline static HeapWord* align_allocation_or_fail(HeapWord* addr, - HeapWord* end, - unsigned short alignment_in_bytes); - // Some heaps may offer a contiguous region for shared non-blocking // allocation, via inlined code (by exporting the address of the top and // end fields defining the extent of the contiguous allocation region.) diff --git a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp index 2d03f7a36b4..94b3b50238f 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp @@ -30,43 +30,6 @@ #include "oops/oop.inline.hpp" #include "utilities/align.hpp" -inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr, - HeapWord* end, - unsigned short alignment_in_bytes) { - if (alignment_in_bytes <= ObjectAlignmentInBytes) { - return addr; - } - - assert(is_aligned(addr, HeapWordSize), - "Address " PTR_FORMAT " is not properly aligned.", p2i(addr)); - assert(is_aligned(alignment_in_bytes, HeapWordSize), - "Alignment size %u is incorrect.", alignment_in_bytes); - - HeapWord* new_addr = align_up(addr, alignment_in_bytes); - size_t padding = pointer_delta(new_addr, addr); - - if (padding == 0) { - return addr; - } - - if (padding < CollectedHeap::min_fill_size()) { - padding += alignment_in_bytes / HeapWordSize; - assert(padding >= CollectedHeap::min_fill_size(), - "alignment_in_bytes %u is expect to be larger " - "than the minimum object size", alignment_in_bytes); - new_addr = addr + padding; - } - - assert(new_addr > addr, "Unexpected arithmetic overflow " - PTR_FORMAT " not greater than " PTR_FORMAT, p2i(new_addr), p2i(addr)); - if(new_addr < end) { - CollectedHeap::fill_with_object(addr, padding); - return new_addr; - } else { - return NULL; - } -} - inline oop CollectedHeap::obj_allocate(Klass* klass, int size, TRAPS) { ObjAllocator allocator(klass, size, THREAD); return allocator.allocate(); diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp index 32ac7541e43..70043c430b4 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp @@ -438,22 +438,3 @@ JVMFlag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) { } } -JVMFlag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose) { - if (value != 0) { - if (!is_power_of_2(value)) { - JVMFlag::printError(verbose, - "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be " - "power of 2\n", - value); - return JVMFlag::VIOLATES_CONSTRAINT; - } - if (value < ObjectAlignmentInBytes) { - JVMFlag::printError(verbose, - "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be " - "greater than or equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n", - value, ObjectAlignmentInBytes); - return JVMFlag::VIOLATES_CONSTRAINT; - } - } - return JVMFlag::SUCCESS; -} diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp index 1f9ecbd40f6..5bbfac68b66 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp @@ -67,8 +67,7 @@ f(uintx, TLABWasteIncrementConstraintFunc) \ f(uintx, SurvivorRatioConstraintFunc) \ f(size_t, MetaspaceSizeConstraintFunc) \ - f(size_t, MaxMetaspaceSizeConstraintFunc) \ - f(intx, SurvivorAlignmentInBytesConstraintFunc) + f(size_t, MaxMetaspaceSizeConstraintFunc) SHARED_GC_CONSTRAINTS(DECLARE_CONSTRAINT) diff --git a/src/hotspot/share/gc/shared/plab.inline.hpp b/src/hotspot/share/gc/shared/plab.inline.hpp index 38ef672f7c8..b0698da8a33 100644 --- a/src/hotspot/share/gc/shared/plab.inline.hpp +++ b/src/hotspot/share/gc/shared/plab.inline.hpp @@ -30,18 +30,6 @@ #include "memory/allocation.inline.hpp" #include "runtime/atomic.hpp" -inline HeapWord* PLAB::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) { - HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes); - if (res == NULL) { - return NULL; - } - - // Set _top so that allocate(), which expects _top to be correctly set, - // can be used below. - _top = res; - return allocate(word_sz); -} - void PLABStats::add_allocated(size_t v) { Atomic::add(&_allocated, v); } diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index c267f1c0c3e..7b099a7d01a 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -567,27 +567,6 @@ inline HeapWord* ContiguousSpace::par_allocate_impl(size_t size) { } while (true); } -HeapWord* ContiguousSpace::allocate_aligned(size_t size) { - assert(Heap_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()), "not locked"); - HeapWord* end_value = end(); - - HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end_value, SurvivorAlignmentInBytes); - if (obj == NULL) { - return NULL; - } - - if (pointer_delta(end_value, obj) >= size) { - HeapWord* new_top = obj + size; - set_top(new_top); - assert(::is_aligned(obj, SurvivorAlignmentInBytes) && is_aligned(new_top), - "checking alignment"); - return obj; - } else { - set_top(obj); - return NULL; - } -} - // Requires locking. HeapWord* ContiguousSpace::allocate(size_t size) { return allocate_impl(size); diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 0b760364bbc..48eadafaf80 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -560,7 +560,6 @@ class ContiguousSpace: public CompactibleSpace { // Allocation (return NULL if full) virtual HeapWord* allocate(size_t word_size); virtual HeapWord* par_allocate(size_t word_size); - HeapWord* allocate_aligned(size_t word_size); // Iteration void oop_iterate(OopIterateClosure* cl); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 19b01ddfd58..a78db987ac7 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" @@ -1058,14 +1059,19 @@ Node* ShenandoahBarrierSetC2::ideal_node(PhaseGVN* phase, Node* n, bool can_resh if (n->Opcode() == Op_CmpP) { Node* in1 = n->in(1); Node* in2 = n->in(2); + + // If one input is NULL, then step over the barriers (except LRB native) on the other input if (in1->bottom_type() == TypePtr::NULL_PTR && - (in1->Opcode() != Op_ShenandoahLoadReferenceBarrier || !((ShenandoahLoadReferenceBarrierNode*)in1)->is_native())) { + !((in2->Opcode() == Op_ShenandoahLoadReferenceBarrier) && + ((ShenandoahLoadReferenceBarrierNode*)in2)->is_native())) { in2 = step_over_gc_barrier(in2); } if (in2->bottom_type() == TypePtr::NULL_PTR && - (in2->Opcode() != Op_ShenandoahLoadReferenceBarrier || !((ShenandoahLoadReferenceBarrierNode*)in2)->is_native())) { + !((in1->Opcode() == Op_ShenandoahLoadReferenceBarrier) && + ((ShenandoahLoadReferenceBarrierNode*)in1)->is_native())) { in1 = step_over_gc_barrier(in1); } + PhaseIterGVN* igvn = phase->is_IterGVN(); if (in1 != n->in(1)) { if (igvn != NULL) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp index f1504b1d46d..fb1e0b0b2fd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp @@ -133,7 +133,7 @@ inline void ShenandoahConcurrentMark::do_chunked_array_start(ShenandoahObjToScan assert(pushed, "overflow queue should always succeed pushing"); } - // Split out tasks, as suggested in ObjArrayChunkedTask docs. Record the last + // Split out tasks, as suggested in ShenandoahMarkTask docs. Record the last // successful right boundary to figure out the irregular tail. while ((1 << pow) > (int)ObjArrayMarkingStride && (chunk*2 < ShenandoahMarkTask::chunk_size())) { @@ -166,7 +166,7 @@ inline void ShenandoahConcurrentMark::do_chunked_array(ShenandoahObjToScanQueue* assert (ObjArrayMarkingStride > 0, "sanity"); - // Split out tasks, as suggested in ObjArrayChunkedTask docs. Avoid pushing tasks that + // Split out tasks, as suggested in ShenandoahMarkTask docs. Avoid pushing tasks that // are known to start beyond the array. while ((1 << pow) > (int)ObjArrayMarkingStride && (chunk*2 < ShenandoahMarkTask::chunk_size())) { pow--; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index c10c24ce795..67adf336996 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -184,14 +184,14 @@ jint ShenandoahHeap::initialize() { assert((((size_t) base()) & ShenandoahHeapRegion::region_size_bytes_mask()) == 0, "Misaligned heap: " PTR_FORMAT, p2i(base())); -#if SHENANDOAH_OPTIMIZED_OBJTASK - // The optimized ObjArrayChunkedTask takes some bits away from the full object bits. +#if SHENANDOAH_OPTIMIZED_MARKTASK + // The optimized ShenandoahMarkTask takes some bits away from the full object bits. // Fail if we ever attempt to address more than we can. - if ((uintptr_t)heap_rs.end() >= ObjArrayChunkedTask::max_addressable()) { + if ((uintptr_t)heap_rs.end() >= ShenandoahMarkTask::max_addressable()) { FormatBuffer<512> buf("Shenandoah reserved [" PTR_FORMAT ", " PTR_FORMAT") for the heap, \n" "but max object address is " PTR_FORMAT ". Try to reduce heap size, or try other \n" "VM options that allocate heap at lower addresses (HeapBaseMinAddress, AllocateHeapAt, etc).", - p2i(heap_rs.base()), p2i(heap_rs.end()), ObjArrayChunkedTask::max_addressable()); + p2i(heap_rs.base()), p2i(heap_rs.end()), ShenandoahMarkTask::max_addressable()); vm_exit_during_initialization("Fatal Error", buf); } #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index d2a2a4cd19a..6e3c826a80e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -29,7 +29,7 @@ #include "classfile/classLoaderDataGraph.hpp" #include "code/codeCache.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" -#include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahRootVerifier.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" @@ -41,15 +41,17 @@ #include "utilities/debug.hpp" ShenandoahGCStateResetter::ShenandoahGCStateResetter() : - _gc_state(ShenandoahHeap::heap()->gc_state()), + _heap(ShenandoahHeap::heap()), + _gc_state(_heap->gc_state()), _concurrent_weak_root_in_progress(ShenandoahHeap::heap()->is_concurrent_weak_root_in_progress()) { + _heap->_gc_state.clear(); + _heap->set_concurrent_weak_root_in_progress(false); } ShenandoahGCStateResetter::~ShenandoahGCStateResetter() { - ShenandoahHeap* const heap = ShenandoahHeap::heap(); - heap->_gc_state.set(_gc_state); - assert(heap->gc_state() == _gc_state, "Should be restored"); - heap->set_concurrent_weak_root_in_progress(_concurrent_weak_root_in_progress); + _heap->_gc_state.set(_gc_state); + assert(_heap->gc_state() == _gc_state, "Should be restored"); + _heap->set_concurrent_weak_root_in_progress(_concurrent_weak_root_in_progress); } // Check for overflow of number of root types. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp index a0171a684cf..3668c240190 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp @@ -30,6 +30,7 @@ class ShenandoahGCStateResetter : public StackObj { private: + ShenandoahHeap* const _heap; const char _gc_state; const bool _concurrent_weak_root_in_progress; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp index 0881779c9d9..3ad8f779e1f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp @@ -32,6 +32,7 @@ #include "runtime/atomic.hpp" #include "runtime/mutex.hpp" #include "runtime/thread.hpp" +#include "utilities/debug.hpp" template class BufferedOverflowTaskQueue: public OverflowTaskQueue @@ -60,7 +61,7 @@ class BufferedOverflowTaskQueue: public OverflowTaskQueue E _elem; }; -// ObjArrayChunkedTask +// ShenandoahMarkTask // // Encodes both regular oops, and the array oops plus chunking data for parallel array processing. // The design goal is to make the regular oop ops very fast, because that would be the prevailing @@ -123,54 +124,54 @@ class BufferedOverflowTaskQueue: public OverflowTaskQueue #endif #ifdef _LP64 -#define SHENANDOAH_OPTIMIZED_OBJTASK 1 +#define SHENANDOAH_OPTIMIZED_MARKTASK 1 #else -#define SHENANDOAH_OPTIMIZED_OBJTASK 0 +#define SHENANDOAH_OPTIMIZED_MARKTASK 0 #endif -#if SHENANDOAH_OPTIMIZED_OBJTASK -class ObjArrayChunkedTask +#if SHENANDOAH_OPTIMIZED_MARKTASK +class ShenandoahMarkTask { -public: - enum { - chunk_bits = 10, - pow_bits = 5, - oop_bits = sizeof(uintptr_t)*8 - chunk_bits - pow_bits - }; - enum { - oop_shift = 0, - pow_shift = oop_shift + oop_bits, - chunk_shift = pow_shift + pow_bits - }; +private: + // Everything is encoded into this field... + uintptr_t _obj; -public: - ObjArrayChunkedTask(oop o = NULL) { - assert(decode_oop(encode_oop(o)) == o, "oop can be encoded: " PTR_FORMAT, p2i(o)); - _obj = encode_oop(o); - } - ObjArrayChunkedTask(oop o, int chunk, int pow) { - assert(decode_oop(encode_oop(o)) == o, "oop can be encoded: " PTR_FORMAT, p2i(o)); - assert(decode_chunk(encode_chunk(chunk)) == chunk, "chunk can be encoded: %d", chunk); - assert(decode_pow(encode_pow(pow)) == pow, "pow can be encoded: %d", pow); - _obj = encode_oop(o) | encode_chunk(chunk) | encode_pow(pow); - } + // ...with these: + static const uint8_t chunk_bits = 10; + static const uint8_t pow_bits = 5; + static const uint8_t oop_bits = sizeof(uintptr_t)*8 - chunk_bits - pow_bits; - // Trivially copyable. + static const uint8_t oop_shift = 0; + static const uint8_t pow_shift = oop_bits; + static const uint8_t chunk_shift = oop_bits + pow_bits; + + static const uintptr_t oop_extract_mask = right_n_bits(oop_bits); + static const uintptr_t chunk_pow_extract_mask = ~right_n_bits(oop_bits); + + static const int chunk_range_mask = right_n_bits(chunk_bits); + static const int pow_range_mask = right_n_bits(pow_bits); inline oop decode_oop(uintptr_t val) const { - return (oop) reinterpret_cast((val >> oop_shift) & right_n_bits(oop_bits)); + STATIC_ASSERT(oop_shift == 0); + return cast_to_oop(val & oop_extract_mask); + } + + inline bool decode_not_chunked(uintptr_t val) const { + // No need to shift for a comparison to zero + return (val & chunk_pow_extract_mask) == 0; } inline int decode_chunk(uintptr_t val) const { - return (int) ((val >> chunk_shift) & right_n_bits(chunk_bits)); + return (int) ((val >> chunk_shift) & chunk_range_mask); } inline int decode_pow(uintptr_t val) const { - return (int) ((val >> pow_shift) & right_n_bits(pow_bits)); + return (int) ((val >> pow_shift) & pow_range_mask); } inline uintptr_t encode_oop(oop obj) const { - return ((uintptr_t)(void*) obj) << oop_shift; + STATIC_ASSERT(oop_shift == 0); + return cast_from_oop(obj); } inline uintptr_t encode_chunk(int chunk) const { @@ -181,12 +182,36 @@ class ObjArrayChunkedTask return ((uintptr_t) pow) << pow_shift; } - inline oop obj() const { return decode_oop(_obj); } - inline int chunk() const { return decode_chunk(_obj); } - inline int pow() const { return decode_pow(_obj); } - inline bool is_not_chunked() const { return (_obj & ~right_n_bits(oop_bits + pow_bits)) == 0; } +public: + ShenandoahMarkTask(oop o = NULL) { + uintptr_t enc = encode_oop(o); + assert(decode_oop(enc) == o, "oop encoding should work: " PTR_FORMAT, p2i(o)); + assert(decode_not_chunked(enc), "task should not be chunked"); + _obj = enc; + } + + ShenandoahMarkTask(oop o, int chunk, int pow) { + uintptr_t enc_oop = encode_oop(o); + uintptr_t enc_chunk = encode_chunk(chunk); + uintptr_t enc_pow = encode_pow(pow); + uintptr_t enc = enc_oop | enc_chunk | enc_pow; + assert(decode_oop(enc) == o, "oop encoding should work: " PTR_FORMAT, p2i(o)); + assert(decode_chunk(enc) == chunk, "chunk encoding should work: %d", chunk); + assert(decode_pow(enc) == pow, "pow encoding should work: %d", pow); + assert(!decode_not_chunked(enc), "task should be chunked"); + _obj = enc; + } + + // Trivially copyable. + +public: + inline oop obj() const { return decode_oop(_obj); } + inline int chunk() const { return decode_chunk(_obj); } + inline int pow() const { return decode_pow(_obj); } - DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. + inline bool is_not_chunked() const { return decode_not_chunked(_obj); } + + DEBUG_ONLY(bool is_valid() const;) // Tasks to be pushed/popped must be valid. static uintptr_t max_addressable() { return nth_bit(oop_bits); @@ -195,35 +220,35 @@ class ObjArrayChunkedTask static int chunk_size() { return nth_bit(chunk_bits); } - -private: - uintptr_t _obj; }; #else -class ObjArrayChunkedTask +class ShenandoahMarkTask { -public: +private: enum { chunk_bits = 10, pow_bits = 5, }; + + oop _obj; + int _chunk; + int _pow; + public: - ObjArrayChunkedTask(oop o = NULL, int chunk = 0, int pow = 0): _obj(o) { + ShenandoahMarkTask(oop o = NULL, int chunk = 0, int pow = 0): + _obj(o), _chunk(chunk), _pow(pow) { assert(0 <= chunk && chunk < nth_bit(chunk_bits), "chunk is sane: %d", chunk); assert(0 <= pow && pow < nth_bit(pow_bits), "pow is sane: %d", pow); - _chunk = chunk; - _pow = pow; } // Trivially copyable. - inline oop obj() const { return _obj; } - inline int chunk() const { return _chunk; } - inline int pow() const { return _pow; } - + inline oop obj() const { return _obj; } + inline int chunk() const { return _chunk; } + inline int pow() const { return _pow; } inline bool is_not_chunked() const { return _chunk == 0; } - DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. + DEBUG_ONLY(bool is_valid() const;) // Tasks to be pushed/popped must be valid. static size_t max_addressable() { return sizeof(oop); @@ -232,19 +257,13 @@ class ObjArrayChunkedTask static int chunk_size() { return nth_bit(chunk_bits); } - -private: - oop _obj; - int _chunk; - int _pow; }; -#endif // SHENANDOAH_OPTIMIZED_OBJTASK +#endif // SHENANDOAH_OPTIMIZED_MARKTASK #ifdef _MSC_VER #pragma warning(pop) #endif -typedef ObjArrayChunkedTask ShenandoahMarkTask; typedef BufferedOverflowTaskQueue ShenandoahBufferedOverflowTaskQueue; typedef Padded ShenandoahObjToScanQueue; diff --git a/src/hotspot/share/gc/z/zAttachedArray.hpp b/src/hotspot/share/gc/z/zAttachedArray.hpp index 319a9084e12..edbdeafadef 100644 --- a/src/hotspot/share/gc/z/zAttachedArray.hpp +++ b/src/hotspot/share/gc/z/zAttachedArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,12 @@ class ZAttachedArray { const size_t _length; static size_t object_size(); + static size_t array_size(size_t length); public: + template + static void* alloc(Allocator* allocator, size_t length); + static void* alloc(size_t length); static void free(ObjectT* obj); diff --git a/src/hotspot/share/gc/z/zAttachedArray.inline.hpp b/src/hotspot/share/gc/z/zAttachedArray.inline.hpp index 81015e44b94..f52f83186e4 100644 --- a/src/hotspot/share/gc/z/zAttachedArray.inline.hpp +++ b/src/hotspot/share/gc/z/zAttachedArray.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,13 +34,35 @@ inline size_t ZAttachedArray::object_size() { } template -inline void* ZAttachedArray::alloc(size_t length) { - const size_t array_size = sizeof(ArrayT) * length; - char* const addr = AllocateHeap(object_size() + array_size, mtGC); - ::new (addr + object_size()) ArrayT[length]; +inline size_t ZAttachedArray::array_size(size_t length) { + return sizeof(ArrayT) * length; +} + +template +template +inline void* ZAttachedArray::alloc(Allocator* allocator, size_t length) { + // Allocate memory for object and array + const size_t size = object_size() + array_size(length); + void* const addr = allocator->alloc(size); + + // Placement new array + void* const array_addr = reinterpret_cast(addr) + object_size(); + ::new (array_addr) ArrayT[length]; + + // Return pointer to object return addr; } +template +inline void* ZAttachedArray::alloc(size_t length) { + struct Allocator { + void* alloc(size_t size) const { + return AllocateHeap(size, mtGC); + } + } allocator; + return alloc(&allocator, length); +} + template inline void ZAttachedArray::free(ObjectT* obj) { FreeHeap(obj); diff --git a/src/hotspot/share/gc/z/zForwarding.cpp b/src/hotspot/share/gc/z/zForwarding.cpp index 6ccd2ea4478..139ff6443d8 100644 --- a/src/hotspot/share/gc/z/zForwarding.cpp +++ b/src/hotspot/share/gc/z/zForwarding.cpp @@ -23,31 +23,7 @@ #include "precompiled.hpp" #include "gc/z/zForwarding.inline.hpp" -#include "gc/z/zPage.inline.hpp" #include "utilities/debug.hpp" -#include "utilities/powerOfTwo.hpp" - -ZForwarding* ZForwarding::create(ZPage* page) { - // Allocate table for linear probing. The size of the table must be - // a power of two to allow for quick and inexpensive indexing/masking. - // The table is sized to have a load factor of 50%, i.e. sized to have - // double the number of entries actually inserted. - assert(page->live_objects() > 0, "Invalid value"); - const size_t nentries = round_up_power_of_2(page->live_objects() * 2); - return ::new (AttachedArray::alloc(nentries)) ZForwarding(page, nentries); -} - -void ZForwarding::destroy(ZForwarding* forwarding) { - AttachedArray::free(forwarding); -} - -ZForwarding::ZForwarding(ZPage* page, size_t nentries) : - _virtual(page->virtual_memory()), - _object_alignment_shift(page->object_alignment_shift()), - _entries(nentries), - _page(page), - _refcount(1), - _pinned(false) {} void ZForwarding::verify() const { guarantee(_refcount > 0, "Invalid refcount"); diff --git a/src/hotspot/share/gc/z/zForwarding.hpp b/src/hotspot/share/gc/z/zForwarding.hpp index b91e6f702c8..6a5bde71908 100644 --- a/src/hotspot/share/gc/z/zForwarding.hpp +++ b/src/hotspot/share/gc/z/zForwarding.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "gc/z/zForwardingEntry.hpp" #include "gc/z/zVirtualMemory.hpp" +class ZForwardingAllocator; class ZPage; typedef size_t ZForwardingCursor; @@ -57,8 +58,8 @@ class ZForwarding { ZForwarding(ZPage* page, size_t nentries); public: - static ZForwarding* create(ZPage* page); - static void destroy(ZForwarding* forwarding); + static uint32_t nentries(const ZPage* page); + static ZForwarding* alloc(ZForwardingAllocator* allocator, ZPage* page); uintptr_t start() const; size_t size() const; diff --git a/src/hotspot/share/gc/z/zForwarding.inline.hpp b/src/hotspot/share/gc/z/zForwarding.inline.hpp index a142f30952e..80bb72002e1 100644 --- a/src/hotspot/share/gc/z/zForwarding.inline.hpp +++ b/src/hotspot/share/gc/z/zForwarding.inline.hpp @@ -26,11 +26,38 @@ #include "gc/z/zAttachedArray.inline.hpp" #include "gc/z/zForwarding.hpp" +#include "gc/z/zForwardingAllocator.inline.hpp" #include "gc/z/zHash.inline.hpp" #include "gc/z/zHeap.hpp" +#include "gc/z/zPage.inline.hpp" #include "gc/z/zVirtualMemory.inline.hpp" #include "runtime/atomic.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" + +inline uint32_t ZForwarding::nentries(const ZPage* page) { + // The number returned by the function is used to size the hash table of + // forwarding entries for this page. This hash table uses linear probing. + // The size of the table must be a power of two to allow for quick and + // inexpensive indexing/masking. The table is also sized to have a load + // factor of 50%, i.e. sized to have double the number of entries actually + // inserted, to allow for good lookup/insert performance. + return round_up_power_of_2(page->live_objects() * 2); +} + +inline ZForwarding* ZForwarding::alloc(ZForwardingAllocator* allocator, ZPage* page) { + const size_t nentries = ZForwarding::nentries(page); + void* const addr = AttachedArray::alloc(allocator, nentries); + return ::new (addr) ZForwarding(page, nentries); +} + +inline ZForwarding::ZForwarding(ZPage* page, size_t nentries) : + _virtual(page->virtual_memory()), + _object_alignment_shift(page->object_alignment_shift()), + _entries(nentries), + _page(page), + _refcount(1), + _pinned(false) {} inline uintptr_t ZForwarding::start() const { return _virtual.start(); diff --git a/src/hotspot/share/gc/z/zForwardingAllocator.cpp b/src/hotspot/share/gc/z/zForwardingAllocator.cpp new file mode 100644 index 00000000000..6550259966b --- /dev/null +++ b/src/hotspot/share/gc/z/zForwardingAllocator.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zForwardingAllocator.hpp" +#include "memory/allocation.inline.hpp" + +ZForwardingAllocator::ZForwardingAllocator() : + _start(NULL), + _end(NULL), + _top(NULL) {} + +ZForwardingAllocator::~ZForwardingAllocator() { + FREE_C_HEAP_ARRAY(char, _start); +} + +void ZForwardingAllocator::reset(size_t size) { + _start = _top = REALLOC_C_HEAP_ARRAY(char, _start, size, mtGC); + _end = _start + size; +} diff --git a/src/hotspot/share/gc/z/zForwardingAllocator.hpp b/src/hotspot/share/gc/z/zForwardingAllocator.hpp new file mode 100644 index 00000000000..8424fe6cd70 --- /dev/null +++ b/src/hotspot/share/gc/z/zForwardingAllocator.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZFORWARDINGALLOCATOR_HPP +#define SHARE_GC_Z_ZFORWARDINGALLOCATOR_HPP + +#include "utilities/globalDefinitions.hpp" + +class ZForwardingAllocator { +private: + char* _start; + char* _end; + char* _top; + +public: + ZForwardingAllocator(); + ~ZForwardingAllocator(); + + void reset(size_t size); + size_t size() const; + bool is_full() const; + + void* alloc(size_t size); +}; + +#endif // SHARE_GC_Z_ZFORWARDINGALLOCATOR_HPP diff --git a/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp b/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp new file mode 100644 index 00000000000..ed191bb025c --- /dev/null +++ b/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZFORWARDINGALLOCATOR_INLINE_HPP +#define SHARE_GC_Z_ZFORWARDINGALLOCATOR_INLINE_HPP + +#include "gc/z/zForwardingAllocator.hpp" +#include "utilities/debug.hpp" + +inline size_t ZForwardingAllocator::size() const { + return _end - _start; +} + +inline bool ZForwardingAllocator::is_full() const { + return _top == _end; +} + +inline void* ZForwardingAllocator::alloc(size_t size) { + char* const addr = _top; + _top += size; + assert(_top <= _end, "Allocation should never fail"); + return addr; +} + +#endif // SHARE_GC_Z_ZFORWARDINGALLOCATOR_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index b172e46c703..367e276a35a 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -126,6 +126,17 @@ class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure { CodeBlobToOopClosure code_cl(this, false /* fix_oop_relocations */); thread->oops_do(this, &code_cl); } + + virtual ZNMethodEntry nmethod_entry() const { + if (ClassUnloading) { + // All encountered nmethods should have been "entered" during stack walking + return ZNMethodEntry::VerifyDisarmed; + } else { + // All nmethods are considered roots and will be visited. + // Make sure that the unvisited gets fixed and disarmed before proceeding. + return ZNMethodEntry::PreBarrier; + } + } }; template @@ -160,12 +171,6 @@ class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure { virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } - -#ifdef ASSERT - virtual bool should_verify_oops() { - return false; - } -#endif }; ZHeapIterator::ZHeapIterator(uint nworkers, bool visit_weaks) : diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index 421dc28b348..df47f690228 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -582,8 +582,9 @@ class ZMarkConcurrentRootsIteratorClosure : public ZRootsIteratorClosure { ZThreadLocalAllocBuffer::publish_statistics(); } - virtual bool should_disarm_nmethods() const { - return true; + virtual ZNMethodEntry nmethod_entry() const { + // Only apply closure to armed nmethods, and then disarm them. + return ZNMethodEntry::Disarm; } virtual void do_thread(Thread* thread) { diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index 16c0ef15d4e..dfbf38d1dc0 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -236,28 +236,42 @@ void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) { class ZNMethodToOopsDoClosure : public NMethodClosure { private: - OopClosure* const _cl; - const bool _should_disarm_nmethods; + OopClosure* const _cl; + const ZNMethodEntry _entry; + BarrierSetNMethod* const _bs_nm; public: - ZNMethodToOopsDoClosure(OopClosure* cl, bool should_disarm_nmethods) : + ZNMethodToOopsDoClosure(OopClosure* cl, ZNMethodEntry entry) : _cl(cl), - _should_disarm_nmethods(should_disarm_nmethods) {} + _entry(entry), + _bs_nm(BarrierSet::barrier_set()->barrier_set_nmethod()) {} virtual void do_nmethod(nmethod* nm) { + if (_entry == ZNMethodEntry::PreBarrier) { + // Apply entry barrier before proceeding with closure + _bs_nm->nmethod_entry_barrier(nm); + } + ZLocker locker(ZNMethod::lock_for_nmethod(nm)); if (!nm->is_alive()) { return; } - if (_should_disarm_nmethods) { + if (_entry == ZNMethodEntry::Disarm) { + // Apply closure and disarm only armed nmethods if (ZNMethod::is_armed(nm)) { ZNMethod::nmethod_oops_do(nm, _cl); ZNMethod::disarm(nm); } - } else { - ZNMethod::nmethod_oops_do(nm, _cl); + return; } + + if (_entry == ZNMethodEntry::VerifyDisarmed) { + // Only verify + assert(!ZNMethod::is_armed(nm), "Must be disarmed"); + } + + ZNMethod::nmethod_oops_do(nm, _cl); } }; @@ -269,8 +283,8 @@ void ZNMethod::oops_do_end() { ZNMethodTable::nmethods_do_end(); } -void ZNMethod::oops_do(OopClosure* cl, bool should_disarm_nmethods) { - ZNMethodToOopsDoClosure nmethod_cl(cl, should_disarm_nmethods); +void ZNMethod::oops_do(OopClosure* cl, ZNMethodEntry entry) { + ZNMethodToOopsDoClosure nmethod_cl(cl, entry); ZNMethodTable::nmethods_do(&nmethod_cl); } diff --git a/src/hotspot/share/gc/z/zNMethod.hpp b/src/hotspot/share/gc/z/zNMethod.hpp index 1b6117b22c6..66914f1ff25 100644 --- a/src/hotspot/share/gc/z/zNMethod.hpp +++ b/src/hotspot/share/gc/z/zNMethod.hpp @@ -31,6 +31,13 @@ class OopClosure; class ZReentrantLock; class ZWorkers; +enum class ZNMethodEntry { + PreBarrier, + Disarm, + VerifyDisarmed, + None +}; + class ZNMethod : public AllStatic { private: static void attach_gc_data(nmethod* nm); @@ -52,7 +59,7 @@ class ZNMethod : public AllStatic { static void oops_do_begin(); static void oops_do_end(); - static void oops_do(OopClosure* cl, bool should_disarm_nmethods); + static void oops_do(OopClosure* cl, ZNMethodEntry entry); static ZReentrantLock* lock_for_nmethod(nmethod* nm); diff --git a/src/hotspot/share/gc/z/zOopClosures.hpp b/src/hotspot/share/gc/z/zOopClosures.hpp index 2823f92f263..93aede74e57 100644 --- a/src/hotspot/share/gc/z/zOopClosures.hpp +++ b/src/hotspot/share/gc/z/zOopClosures.hpp @@ -31,12 +31,6 @@ class ZLoadBarrierOopClosure : public BasicOopIterateClosure { public: virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - -#ifdef ASSERT - virtual bool should_verify_oops() { - return false; - } -#endif }; class ZNMethodOopClosure : public OopClosure { @@ -52,12 +46,6 @@ class ZMarkBarrierOopClosure : public ClaimMetadataVisitingOopIterateClosure { virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - -#ifdef ASSERT - virtual bool should_verify_oops() { - return false; - } -#endif }; class ZPhantomIsAliveObjectClosure : public BoolObjectClosure { @@ -69,12 +57,16 @@ class ZPhantomKeepAliveOopClosure : public ZRootsIteratorClosure { public: virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); + + virtual ZNMethodEntry nmethod_entry() const; }; class ZPhantomCleanOopClosure : public ZRootsIteratorClosure { public: virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); + + virtual ZNMethodEntry nmethod_entry() const; }; #endif // SHARE_GC_Z_ZOOPCLOSURES_HPP diff --git a/src/hotspot/share/gc/z/zOopClosures.inline.hpp b/src/hotspot/share/gc/z/zOopClosures.inline.hpp index da8f22ff9d8..eb9c7ad92fa 100644 --- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp +++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp @@ -80,6 +80,11 @@ inline void ZPhantomKeepAliveOopClosure::do_oop(oop* p) { ZBarrier::keep_alive_barrier_on_phantom_oop_field(p); } +inline ZNMethodEntry ZPhantomKeepAliveOopClosure::nmethod_entry() const { + ShouldNotReachHere(); + return ZNMethodEntry::None; +} + inline void ZPhantomKeepAliveOopClosure::do_oop(narrowOop* p) { ShouldNotReachHere(); } @@ -104,4 +109,9 @@ inline void ZPhantomCleanOopClosure::do_oop(narrowOop* p) { ShouldNotReachHere(); } +inline ZNMethodEntry ZPhantomCleanOopClosure::nmethod_entry() const { + ShouldNotReachHere(); + return ZNMethodEntry::None; +} + #endif // SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zRelocationSet.cpp b/src/hotspot/share/gc/z/zRelocationSet.cpp index b7f566397ae..72d9fcef2c7 100644 --- a/src/hotspot/share/gc/z/zRelocationSet.cpp +++ b/src/hotspot/share/gc/z/zRelocationSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,35 +22,53 @@ */ #include "precompiled.hpp" -#include "gc/z/zForwarding.hpp" +#include "gc/z/zForwarding.inline.hpp" +#include "gc/z/zForwardingAllocator.inline.hpp" #include "gc/z/zRelocationSet.hpp" +#include "gc/z/zStat.hpp" #include "memory/allocation.hpp" +#include "utilities/debug.hpp" ZRelocationSet::ZRelocationSet() : + _allocator(), _forwardings(NULL), _nforwardings(0) {} -void ZRelocationSet::populate(ZPage* const* group0, size_t ngroup0, - ZPage* const* group1, size_t ngroup1) { - _nforwardings = ngroup0 + ngroup1; - _forwardings = REALLOC_C_HEAP_ARRAY(ZForwarding*, _forwardings, _nforwardings, mtGC); +void ZRelocationSet::populate(ZPage* const* small, size_t nsmall, + ZPage* const* medium, size_t nmedium, + size_t forwarding_entries) { + // Set relocation set length + _nforwardings = nsmall + nmedium; + // Initialize forwarding allocator to have room for the + // relocation set, all forwardings, and all forwarding entries. + const size_t relocation_set_size = _nforwardings * sizeof(ZForwarding*); + const size_t forwardings_size = _nforwardings * sizeof(ZForwarding); + const size_t forwarding_entries_size = forwarding_entries * sizeof(ZForwardingEntry); + _allocator.reset(relocation_set_size + forwardings_size + forwarding_entries_size); + + // Allocate relocation set + _forwardings = new (_allocator.alloc(relocation_set_size)) ZForwarding*[_nforwardings]; + + // Populate relocation set array size_t j = 0; - // Populate group 0 - for (size_t i = 0; i < ngroup0; i++) { - _forwardings[j++] = ZForwarding::create(group0[i]); + // Populate medium pages + for (size_t i = 0; i < nmedium; i++) { + _forwardings[j++] = ZForwarding::alloc(&_allocator, medium[i]); } - // Populate group 1 - for (size_t i = 0; i < ngroup1; i++) { - _forwardings[j++] = ZForwarding::create(group1[i]); + // Populate small pages + for (size_t i = 0; i < nsmall; i++) { + _forwardings[j++] = ZForwarding::alloc(&_allocator, small[i]); } + + assert(_allocator.is_full(), "Should be full"); + + // Update statistics + ZStatRelocation::set_at_populate_relocation_set(_allocator.size()); } void ZRelocationSet::reset() { - for (size_t i = 0; i < _nforwardings; i++) { - ZForwarding::destroy(_forwardings[i]); - _forwardings[i] = NULL; - } + _nforwardings = 0; } diff --git a/src/hotspot/share/gc/z/zRelocationSet.hpp b/src/hotspot/share/gc/z/zRelocationSet.hpp index 21dff8a16e9..2bf6ccb9de6 100644 --- a/src/hotspot/share/gc/z/zRelocationSet.hpp +++ b/src/hotspot/share/gc/z/zRelocationSet.hpp @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZRELOCATIONSET_HPP #include "gc/z/zArray.hpp" +#include "gc/z/zForwardingAllocator.hpp" #include "memory/allocation.hpp" class ZForwarding; @@ -34,14 +35,16 @@ class ZRelocationSet { template friend class ZRelocationSetIteratorImpl; private: - ZForwarding** _forwardings; - size_t _nforwardings; + ZForwardingAllocator _allocator; + ZForwarding** _forwardings; + size_t _nforwardings; public: ZRelocationSet(); - void populate(ZPage* const* group0, size_t ngroup0, - ZPage* const* group1, size_t ngroup1); + void populate(ZPage* const* small, size_t nsmall, + ZPage* const* medium, size_t nmedium, + size_t forwarding_entries); void reset(); }; diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp index ac33451735e..5239ef0b0cc 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp @@ -23,6 +23,7 @@ #include "precompiled.hpp" #include "gc/z/zArray.inline.hpp" +#include "gc/z/zForwarding.inline.hpp" #include "gc/z/zPage.inline.hpp" #include "gc/z/zRelocationSet.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp" @@ -53,6 +54,7 @@ ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name, _registered_pages(), _sorted_pages(NULL), _nselected(0), + _forwarding_entries(0), _stats() {} ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() { @@ -143,19 +145,23 @@ void ZRelocationSetSelectorGroup::select_inner() { const size_t npages = _registered_pages.length(); size_t selected_from = 0; size_t selected_to = 0; - size_t from_size = 0; + size_t selected_forwarding_entries = 0; + size_t from_live_bytes = 0; + size_t from_forwarding_entries = 0; semi_sort(); for (size_t from = 1; from <= npages; from++) { // Add page to the candidate relocation set - from_size += _sorted_pages[from - 1]->live_bytes(); + ZPage* const page = _sorted_pages[from - 1]; + from_live_bytes += page->live_bytes(); + from_forwarding_entries += ZForwarding::nentries(page); // Calculate the maximum number of pages needed by the candidate relocation set. // By subtracting the object size limit from the pages size we get the maximum // number of pages that the relocation set is guaranteed to fit in, regardless // of in which order the objects are relocated. - const size_t to = ceil((double)(from_size) / (double)(_page_size - _object_size_limit)); + const size_t to = ceil((double)(from_live_bytes) / (double)(_page_size - _object_size_limit)); // Calculate the relative difference in reclaimable space compared to our // currently selected final relocation set. If this number is larger than the @@ -167,22 +173,27 @@ void ZRelocationSetSelectorGroup::select_inner() { if (diff_reclaimable > ZFragmentationLimit) { selected_from = from; selected_to = to; + selected_forwarding_entries = from_forwarding_entries; } - log_trace(gc, reloc)("Candidate Relocation Set (%s Pages): " - SIZE_FORMAT "->" SIZE_FORMAT ", %.1f%% relative defragmentation, %s", - _name, from, to, diff_reclaimable, (selected_from == from) ? "Selected" : "Rejected"); + log_trace(gc, reloc)("Candidate Relocation Set (%s Pages): " SIZE_FORMAT "->" SIZE_FORMAT ", " + "%.1f%% relative defragmentation, " SIZE_FORMAT " forwarding entries, %s", + _name, from, to, diff_reclaimable, from_forwarding_entries, + (selected_from == from) ? "Selected" : "Rejected"); } // Finalize selection _nselected = selected_from; + _forwarding_entries = selected_forwarding_entries; // Update statistics _stats._compacting_from = selected_from * _page_size; _stats._compacting_to = selected_to * _page_size; - log_trace(gc, reloc)("Relocation Set (%s Pages): " SIZE_FORMAT "->" SIZE_FORMAT ", " SIZE_FORMAT " skipped", - _name, selected_from, selected_to, npages - _nselected); + log_trace(gc, reloc)("Relocation Set (%s Pages): " SIZE_FORMAT "->" SIZE_FORMAT ", " + SIZE_FORMAT " skipped, " SIZE_FORMAT " forwarding entries", + _name, selected_from, selected_to, npages - selected_from, + selected_forwarding_entries); } void ZRelocationSetSelectorGroup::select() { @@ -245,8 +256,9 @@ void ZRelocationSetSelector::select(ZRelocationSet* relocation_set) { _small.select(); // Populate relocation set - relocation_set->populate(_medium.selected(), _medium.nselected(), - _small.selected(), _small.nselected()); + relocation_set->populate(_small.selected(), _small.nselected(), + _medium.selected(), _medium.nselected(), + forwarding_entries()); // Send event event.commit(total(), empty(), compacting_from(), compacting_to()); diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp index 70900f814d8..034cee6e097 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp @@ -75,10 +75,10 @@ class ZRelocationSetSelectorGroup { const size_t _page_size; const size_t _object_size_limit; const size_t _fragmentation_limit; - ZArray _registered_pages; ZPage** _sorted_pages; size_t _nselected; + size_t _forwarding_entries; ZRelocationSetSelectorGroupStats _stats; bool is_disabled(); @@ -99,6 +99,7 @@ class ZRelocationSetSelectorGroup { ZPage* const* selected() const; size_t nselected() const; + size_t forwarding_entries() const; const ZRelocationSetSelectorGroupStats& stats() const; }; @@ -109,6 +110,7 @@ class ZRelocationSetSelector : public StackObj { ZRelocationSetSelectorGroup _medium; ZRelocationSetSelectorGroup _large; + size_t forwarding_entries() const; size_t total() const; size_t empty() const; size_t compacting_from() const; diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp b/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp index 37b7839511d..1017a09071b 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp @@ -74,10 +74,18 @@ inline size_t ZRelocationSetSelectorGroup::nselected() const { return _nselected; } +inline size_t ZRelocationSetSelectorGroup::forwarding_entries() const { + return _forwarding_entries; +} + inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stats() const { return _stats; } +inline size_t ZRelocationSetSelector::forwarding_entries() const { + return _small.forwarding_entries() + _medium.forwarding_entries(); +} + inline size_t ZRelocationSetSelector::total() const { return _small.stats().total() + _medium.stats().total() + _large.stats().total(); } diff --git a/src/hotspot/share/gc/z/zRootsIterator.cpp b/src/hotspot/share/gc/z/zRootsIterator.cpp index 5d5e7190c8a..3ddda27b8d5 100644 --- a/src/hotspot/share/gc/z/zRootsIterator.cpp +++ b/src/hotspot/share/gc/z/zRootsIterator.cpp @@ -122,7 +122,7 @@ void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* void ZConcurrentRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) { ZStatTimer timer(ZSubPhaseConcurrentRootsCodeCache); - ZNMethod::oops_do(cl, cl->should_disarm_nmethods()); + ZNMethod::oops_do(cl, cl->nmethod_entry()); } class ZConcurrentRootsIteratorThreadClosure : public ThreadClosure { diff --git a/src/hotspot/share/gc/z/zRootsIterator.hpp b/src/hotspot/share/gc/z/zRootsIterator.hpp index 87626b09ab1..49e87cd9799 100644 --- a/src/hotspot/share/gc/z/zRootsIterator.hpp +++ b/src/hotspot/share/gc/z/zRootsIterator.hpp @@ -26,6 +26,7 @@ #include "classfile/classLoaderDataGraph.hpp" #include "gc/shared/oopStorageSetParState.hpp" +#include "gc/z/zNMethod.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" #include "runtime/threadSMR.hpp" @@ -61,9 +62,7 @@ class ZRootsIteratorClosure : public OopClosure { public: virtual void do_thread(Thread* thread) {} - virtual bool should_disarm_nmethods() const { - return false; - } + virtual ZNMethodEntry nmethod_entry() const = 0; }; class ZJavaThreadsIterator { diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index 73ee5494de0..c1441005eae 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -1140,12 +1140,17 @@ void ZStatMark::print() { // Stat relocation // ZRelocationSetSelectorStats ZStatRelocation::_stats; +size_t ZStatRelocation::_forwarding_usage; bool ZStatRelocation::_success; void ZStatRelocation::set_at_select_relocation_set(const ZRelocationSetSelectorStats& stats) { _stats = stats; } +void ZStatRelocation::set_at_populate_relocation_set(size_t forwarding_usage) { + _forwarding_usage = forwarding_usage; +} + void ZStatRelocation::set_at_relocate_end(bool success) { _success = success; } @@ -1169,6 +1174,7 @@ void ZStatRelocation::print() { } print("Large", _stats.large()); + log_info(gc, reloc)("Forwarding Usage: " SIZE_FORMAT "M", _forwarding_usage / M); log_info(gc, reloc)("Relocation: %s", _success ? "Successful" : "Incomplete"); } diff --git a/src/hotspot/share/gc/z/zStat.hpp b/src/hotspot/share/gc/z/zStat.hpp index 3faac3b8ea5..d8e8c868e5d 100644 --- a/src/hotspot/share/gc/z/zStat.hpp +++ b/src/hotspot/share/gc/z/zStat.hpp @@ -423,12 +423,14 @@ class ZStatMark : public AllStatic { class ZStatRelocation : public AllStatic { private: static ZRelocationSetSelectorStats _stats; + static size_t _forwarding_usage; static bool _success; static void print(const char* name, const ZRelocationSetSelectorGroupStats& group); public: static void set_at_select_relocation_set(const ZRelocationSetSelectorStats& stats); + static void set_at_populate_relocation_set(size_t forwarding_usage); static void set_at_relocate_end(bool success); static void print(); diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index 6ca1ebc888f..a10d64c1e87 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -94,6 +94,11 @@ class ZVerifyRootClosure : public ZRootsIteratorClosure { bool verify_fixed() const { return _verify_fixed; } + + virtual ZNMethodEntry nmethod_entry() const { + // Verification performs its own verification + return ZNMethodEntry::None; + } }; class ZVerifyCodeBlobClosure : public CodeBlobToOopClosure { @@ -188,7 +193,7 @@ void ZVerifyRootClosure::do_thread(Thread* thread) { verify_stack.verify_frames(); } -class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure, public ZRootsIteratorClosure { +class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure { private: const bool _verify_weaks; @@ -214,13 +219,6 @@ class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure, public virtual ReferenceIterationMode reference_iteration_mode() { return _verify_weaks ? DO_FIELDS : DO_FIELDS_EXCEPT_REFERENT; } - -#ifdef ASSERT - // Verification handled by the closure itself - virtual bool should_verify_oops() { - return false; - } -#endif }; template diff --git a/src/hotspot/share/interpreter/interpreter.cpp b/src/hotspot/share/interpreter/interpreter.cpp index f597950f38f..f32bb377466 100644 --- a/src/hotspot/share/interpreter/interpreter.cpp +++ b/src/hotspot/share/interpreter/interpreter.cpp @@ -76,7 +76,7 @@ void InterpreterCodelet::print_on(outputStream* st) const { if (PrintInterpreter) { st->cr(); - Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_strings) NOT_DEBUG(CodeStrings())); + Disassembler::decode(code_begin(), code_end(), st DEBUG_ONLY(COMMA &_strings)); } } @@ -106,7 +106,8 @@ CodeletMark::~CodeletMark() { // Commit Codelet. int committed_code_size = (*_masm)->code()->pure_insts_size(); if (committed_code_size) { - AbstractInterpreter::code()->commit(committed_code_size, (*_masm)->code()->strings()); + CodeStrings cs NOT_PRODUCT(= (*_masm)->code()->strings()); + AbstractInterpreter::code()->commit(committed_code_size, cs); } // Make sure nobody can use _masm outside a CodeletMark lifespan. *_masm = NULL; diff --git a/src/hotspot/share/interpreter/interpreter.hpp b/src/hotspot/share/interpreter/interpreter.hpp index 288aa662eee..ac89b7b2ad0 100644 --- a/src/hotspot/share/interpreter/interpreter.hpp +++ b/src/hotspot/share/interpreter/interpreter.hpp @@ -49,14 +49,14 @@ class InterpreterCodelet: public Stub { int _size; // the size in bytes const char* _description; // a description of the codelet, for debugging & printing Bytecodes::Code _bytecode; // associated bytecode if any - DEBUG_ONLY(CodeStrings _strings;) // Comments for annotating assembler output. + NOT_PRODUCT(CodeStrings _strings;) // Comments for annotating assembler output. public: // Initialization/finalization void initialize(int size, CodeStrings& strings) { _size = size; - DEBUG_ONLY(::new(&_strings) CodeStrings();) - DEBUG_ONLY(_strings.assign(strings);) } + NOT_PRODUCT(_strings = CodeStrings();) + NOT_PRODUCT(_strings.copy(strings);) } void finalize() { ShouldNotCallThis(); } // General info/converters diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 40c7d098009..07d3c0ea0b8 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -1172,10 +1172,7 @@ JRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread)) } JRT_END -JRT_ENTRY(void, InterpreterRuntime::at_unwind(JavaThread* thread)) - // JRT_END does an implicit safepoint check, hence we are guaranteed to block - // if this is called during a safepoint - +JRT_LEAF(void, InterpreterRuntime::at_unwind(JavaThread* thread)) // This function is called by the interpreter when the return poll found a reason // to call the VM. The reason could be that we are returning into a not yet safe // to access frame. We handle that below. diff --git a/src/hotspot/share/interpreter/templateInterpreter.cpp b/src/hotspot/share/interpreter/templateInterpreter.cpp index 4bcd1333891..b65e1d57a8b 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.cpp +++ b/src/hotspot/share/interpreter/templateInterpreter.cpp @@ -104,6 +104,19 @@ EntryPoint::EntryPoint(address bentry, address zentry, address centry, address s _entry[vtos] = ventry; } +EntryPoint::EntryPoint(address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { + assert(number_of_states == 10, "check the code below"); + _entry[btos] = ientry; + _entry[ztos] = ientry; + _entry[ctos] = ientry; + _entry[stos] = ientry; + _entry[atos] = aentry; + _entry[itos] = ientry; + _entry[ltos] = lentry; + _entry[ftos] = fentry; + _entry[dtos] = dentry; + _entry[vtos] = ventry; +} void EntryPoint::set_entry(TosState state, address entry) { assert(0 <= state && state < number_of_states, "state out of bounds"); diff --git a/src/hotspot/share/interpreter/templateInterpreter.hpp b/src/hotspot/share/interpreter/templateInterpreter.hpp index 2ff62e15d33..23a6a7f7007 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.hpp +++ b/src/hotspot/share/interpreter/templateInterpreter.hpp @@ -48,7 +48,8 @@ class EntryPoint { // Construction EntryPoint(); EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); - + // Will use the ientry for each of [bzcs]entry + EntryPoint(address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); // Attributes address entry(TosState state) const; // return target address for a given tosca state void set_entry(TosState state, address entry); // set target address for a given tosca state diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 51b95bbd76b..be26ef206bd 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -68,10 +68,6 @@ void TemplateInterpreterGenerator::generate_all() { CodeletMark cm(_masm, "bytecode tracing support"); Interpreter::_trace_code = EntryPoint( - generate_trace_code(btos), - generate_trace_code(ztos), - generate_trace_code(ctos), - generate_trace_code(stos), generate_trace_code(atos), generate_trace_code(itos), generate_trace_code(ltos), @@ -83,50 +79,54 @@ void TemplateInterpreterGenerator::generate_all() { #endif // !PRODUCT { CodeletMark cm(_masm, "return entry points"); - const int index_size = sizeof(u2); Interpreter::_return_entry[0] = EntryPoint(); for (int i = 1; i < Interpreter::number_of_return_entries; i++) { - address return_itos = generate_return_entry_for(itos, i, index_size); Interpreter::_return_entry[i] = EntryPoint( - return_itos, - return_itos, - return_itos, - return_itos, - generate_return_entry_for(atos, i, index_size), - return_itos, - generate_return_entry_for(ltos, i, index_size), - generate_return_entry_for(ftos, i, index_size), - generate_return_entry_for(dtos, i, index_size), - generate_return_entry_for(vtos, i, index_size) + generate_return_entry_for(atos, i, sizeof(u2)), + generate_return_entry_for(itos, i, sizeof(u2)), + generate_return_entry_for(ltos, i, sizeof(u2)), + generate_return_entry_for(ftos, i, sizeof(u2)), + generate_return_entry_for(dtos, i, sizeof(u2)), + generate_return_entry_for(vtos, i, sizeof(u2)) ); } } { CodeletMark cm(_masm, "invoke return entry points"); - // These states are in order specified in TosState, except btos/ztos/ctos/stos are - // really the same as itos since there is no top of stack optimization for these types - const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl}; + // These states are in order specified in TosState, except btos/ztos/ctos/stos which + // are the same as itos since there is no top of stack optimization for these types + const TosState states[] = {ilgl, ilgl, ilgl, ilgl, itos, ltos, ftos, dtos, atos, vtos, ilgl}; const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); - for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { + assert(invoke_length >= 0 && invoke_length < Interpreter::number_of_return_entries, "invariant"); + assert(invokeinterface_length >= 0 && invokeinterface_length < Interpreter::number_of_return_entries, "invariant"); + + for (int i = itos; i < Interpreter::number_of_return_addrs; i++) { TosState state = states[i]; assert(state != ilgl, "states array is wrong above"); - Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); - Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); - Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); + + // Reuse generated entry points + Interpreter::_invoke_return_entry[i] = Interpreter::_return_entry[invoke_length].entry(state); + Interpreter::_invokeinterface_return_entry[i] = Interpreter::_return_entry[invokeinterface_length].entry(state); + + Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); + } + + // set itos entry points for btos/ztos/ctos/stos + for (int i = 0; i < itos; i++) { + Interpreter::_invoke_return_entry[i] = Interpreter::_invoke_return_entry[itos]; + Interpreter::_invokeinterface_return_entry[i] = Interpreter::_invokeinterface_return_entry[itos]; + Interpreter::_invokedynamic_return_entry[i] = Interpreter::_invokedynamic_return_entry[itos]; } } { CodeletMark cm(_masm, "earlyret entry points"); + address earlyret_entry_itos = generate_earlyret_entry_for(itos); Interpreter::_earlyret_entry = EntryPoint( - generate_earlyret_entry_for(btos), - generate_earlyret_entry_for(ztos), - generate_earlyret_entry_for(ctos), - generate_earlyret_entry_for(stos), generate_earlyret_entry_for(atos), generate_earlyret_entry_for(itos), generate_earlyret_entry_for(ltos), @@ -153,10 +153,6 @@ void TemplateInterpreterGenerator::generate_all() { { CodeletMark cm(_masm, "safepoint entry points"); Interpreter::_safept_entry = EntryPoint( - generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), @@ -242,12 +238,8 @@ void TemplateInterpreterGenerator::generate_all() { address deopt_itos = generate_deopt_entry_for(itos, i); Interpreter::_deopt_entry[i] = EntryPoint( - deopt_itos, /* btos */ - deopt_itos, /* ztos */ - deopt_itos, /* ctos */ - deopt_itos, /* stos */ generate_deopt_entry_for(atos, i), - deopt_itos, /* itos */ + generate_deopt_entry_for(itos, i), generate_deopt_entry_for(ltos, i), generate_deopt_entry_for(ftos, i), generate_deopt_entry_for(dtos, i), diff --git a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp index b722cde50b7..4cc6a716427 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp @@ -64,7 +64,6 @@ class BFSClosure : public BasicOopIterateClosure { public: virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS_EXCEPT_REFERENT; } - virtual bool should_verify_oops() { return false; } BFSClosure(EdgeQueue* edge_queue, EdgeStore* edge_store, BitSet* mark_bits); void process(); diff --git a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp index ba88b8dcd78..ad99f7d2320 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp @@ -54,7 +54,6 @@ class DFSClosure : public BasicOopIterateClosure { public: virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS_EXCEPT_REFERENT; } - virtual bool should_verify_oops() { return false; } static void find_leaks_from_edge(EdgeStore* edge_store, BitSet* mark_bits, const Edge* start_edge); static void find_leaks_from_root_set(EdgeStore* edge_store, BitSet* mark_bits); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index b6d5e37c482..ed9ad397aad 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -1328,29 +1328,23 @@ Method* JVMCIRuntime::lookup_method(InstanceKlass* accessor, // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl(). assert(check_klass_accessibility(accessor, holder), "holder not accessible"); - Method* dest_method; - LinkInfo link_info(holder, name, sig, accessor, LinkInfo::AccessCheck::required, LinkInfo::LoaderConstraintCheck::required, tag); + LinkInfo link_info(holder, name, sig, accessor, + LinkInfo::AccessCheck::required, + LinkInfo::LoaderConstraintCheck::required, + tag); switch (bc) { - case Bytecodes::_invokestatic: - dest_method = - LinkResolver::resolve_static_call_or_null(link_info); - break; - case Bytecodes::_invokespecial: - dest_method = - LinkResolver::resolve_special_call_or_null(link_info); - break; - case Bytecodes::_invokeinterface: - dest_method = - LinkResolver::linktime_resolve_interface_method_or_null(link_info); - break; - case Bytecodes::_invokevirtual: - dest_method = - LinkResolver::linktime_resolve_virtual_method_or_null(link_info); - break; - default: ShouldNotReachHere(); - } - - return dest_method; + case Bytecodes::_invokestatic: + return LinkResolver::resolve_static_call_or_null(link_info); + case Bytecodes::_invokespecial: + return LinkResolver::resolve_special_call_or_null(link_info); + case Bytecodes::_invokeinterface: + return LinkResolver::linktime_resolve_interface_method_or_null(link_info); + case Bytecodes::_invokevirtual: + return LinkResolver::linktime_resolve_virtual_method_or_null(link_info); + default: + fatal("Unhandled bytecode: %s", Bytecodes::name(bc)); + return NULL; // silence compiler warnings + } } diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 74fbe0d81f8..1ee9ddc556f 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -51,6 +51,7 @@ LOG_TAG(classhisto) \ LOG_TAG(cleanup) \ LOG_TAG(codecache) \ + NOT_PRODUCT(LOG_TAG(codestrings)) \ LOG_TAG(compaction) \ LOG_TAG(compilation) \ LOG_TAG(condy) \ diff --git a/src/hotspot/share/memory/archiveBuilder.cpp b/src/hotspot/share/memory/archiveBuilder.cpp index 861328195dd..d53ec907b41 100644 --- a/src/hotspot/share/memory/archiveBuilder.cpp +++ b/src/hotspot/share/memory/archiveBuilder.cpp @@ -38,6 +38,7 @@ #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oopHandle.inline.hpp" +#include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/hashtable.inline.hpp" @@ -45,6 +46,27 @@ ArchiveBuilder* ArchiveBuilder::_singleton = NULL; intx ArchiveBuilder::_buffer_to_target_delta = 0; +class AdapterHandlerEntry; + +class MethodTrampolineInfo { + address _c2i_entry_trampoline; + AdapterHandlerEntry** _adapter_trampoline; +public: + address c2i_entry_trampoline() { return _c2i_entry_trampoline; } + AdapterHandlerEntry** adapter_trampoline() { return _adapter_trampoline; } + void set_c2i_entry_trampoline(address addr) { _c2i_entry_trampoline = addr; } + void set_adapter_trampoline(AdapterHandlerEntry** entry) { _adapter_trampoline = entry; } +}; + +class AdapterToTrampoline : public ResourceHashtable< + AdapterHandlerEntry*, MethodTrampolineInfo, + primitive_hash, + primitive_equals, + 941, // prime number + ResourceObj::C_HEAP> {}; + +static AdapterToTrampoline* _adapter_to_trampoline = NULL; + ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() { char* newtop = ArchiveBuilder::singleton()->_ro_region->top(); ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true); @@ -259,6 +281,8 @@ void ArchiveBuilder::gather_klasses_and_symbols() { // DynamicArchiveBuilder::sort_methods()). sort_symbols_and_fix_hash(); sort_klasses(); + allocate_method_trampoline_info(); + allocate_method_trampolines(); } } @@ -798,3 +822,89 @@ void ArchiveBuilder::clean_up_src_obj_table() { SrcObjTableCleaner cleaner; _src_obj_table.iterate(&cleaner); } + +void ArchiveBuilder::allocate_method_trampolines_for(InstanceKlass* ik) { + if (ik->methods() != NULL) { + for (int j = 0; j < ik->methods()->length(); j++) { + // Walk the methods in a deterministic order so that the trampolines are + // created in a deterministic order. + Method* m = ik->methods()->at(j); + AdapterHandlerEntry* ent = m->adapter(); // different methods can share the same AdapterHandlerEntry + MethodTrampolineInfo* info = _adapter_to_trampoline->get(ent); + if (info->c2i_entry_trampoline() == NULL) { + info->set_c2i_entry_trampoline( + (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size())); + info->set_adapter_trampoline( + (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*))); + } + } + } +} + +void ArchiveBuilder::allocate_method_trampolines() { + for (int i = 0; i < _klasses->length(); i++) { + Klass* k = _klasses->at(i); + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + allocate_method_trampolines_for(ik); + } + } +} + +// Allocate MethodTrampolineInfo for all Methods that will be archived. Also +// return the total number of bytes needed by the method trampolines in the MC +// region. +size_t ArchiveBuilder::allocate_method_trampoline_info() { + size_t total = 0; + size_t each_method_bytes = + align_up(SharedRuntime::trampoline_size(), BytesPerWord) + + align_up(sizeof(AdapterHandlerEntry*), BytesPerWord); + + if (_adapter_to_trampoline == NULL) { + _adapter_to_trampoline = new (ResourceObj::C_HEAP, mtClass)AdapterToTrampoline(); + } + int count = 0; + for (int i = 0; i < _klasses->length(); i++) { + Klass* k = _klasses->at(i); + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->methods() != NULL) { + for (int j = 0; j < ik->methods()->length(); j++) { + Method* m = ik->methods()->at(j); + AdapterHandlerEntry* ent = m->adapter(); // different methods can share the same AdapterHandlerEntry + bool is_created = false; + MethodTrampolineInfo* info = _adapter_to_trampoline->put_if_absent(ent, &is_created); + if (is_created) { + count++; + } + } + } + } + } + if (count == 0) { + // We have nothing to archive, but let's avoid having an empty region. + total = SharedRuntime::trampoline_size(); + } else { + total = count * each_method_bytes; + } + return align_up(total, SharedSpaceObjectAlignment); +} + +void ArchiveBuilder::update_method_trampolines() { + for (int i = 0; i < klasses()->length(); i++) { + Klass* k = klasses()->at(i); + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + Array* methods = ik->methods(); + for (int j = 0; j < methods->length(); j++) { + Method* m = methods->at(j); + AdapterHandlerEntry* ent = m->adapter(); + MethodTrampolineInfo* info = _adapter_to_trampoline->get(ent); + // m is the "copy" of the original Method, but its adapter() field is still valid because + // we haven't called make_klasses_shareable() yet. + m->set_from_compiled_entry(info->c2i_entry_trampoline()); + m->set_adapter_trampoline(info->adapter_trampoline()); + } + } + } +} diff --git a/src/hotspot/share/memory/archiveBuilder.hpp b/src/hotspot/share/memory/archiveBuilder.hpp index 10704de6e3d..e39df1cd897 100644 --- a/src/hotspot/share/memory/archiveBuilder.hpp +++ b/src/hotspot/share/memory/archiveBuilder.hpp @@ -279,6 +279,13 @@ class ArchiveBuilder : public StackObj { void print_stats(int ro_all, int rw_all, int mc_all); static intx _buffer_to_target_delta; + + // Method trampolines related functions + void allocate_method_trampolines(); + void allocate_method_trampolines_for(InstanceKlass* ik); + size_t allocate_method_trampoline_info(); + void update_method_trampolines(); + }; #endif // SHARE_MEMORY_ARCHIVEBUILDER_HPP diff --git a/src/hotspot/share/memory/dynamicArchive.cpp b/src/hotspot/share/memory/dynamicArchive.cpp index 26c17a5faaa..5cb889f60cf 100644 --- a/src/hotspot/share/memory/dynamicArchive.cpp +++ b/src/hotspot/share/memory/dynamicArchive.cpp @@ -93,12 +93,10 @@ class DynamicArchiveBuilder : public ArchiveBuilder { size_t _estimated_trampoline_bytes; // method entry trampolines size_t estimate_archive_size(); - size_t estimate_trampoline_size(); size_t estimate_class_file_size(); address reserve_space_and_init_buffer_to_target_delta(); void init_header(address addr); void release_header(); - void make_trampolines(); void sort_methods(); void sort_methods(InstanceKlass* ik) const; void remark_pointers_for_instance_klass(InstanceKlass* k, bool should_mark) const; @@ -116,12 +114,6 @@ class DynamicArchiveBuilder : public ArchiveBuilder { _num_dump_regions_used = 1; } - void reserve_buffers_for_trampolines() { - size_t n = _estimated_trampoline_bytes; - assert(n >= SharedRuntime::trampoline_size(), "dont want to be empty"); - MetaspaceShared::misc_code_space_alloc(n); - } - public: DynamicArchiveBuilder() : ArchiveBuilder(MetaspaceShared::misc_code_dump_space(), MetaspaceShared::read_write_dump_space(), @@ -184,7 +176,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { CHeapBitMap ptrmap; ArchivePtrMarker::initialize(&ptrmap, (address*)reserved_bottom, (address*)current_dump_space()->top()); - reserve_buffers_for_trampolines(); + allocate_method_trampolines(); verify_estimate_size(_estimated_trampoline_bytes, "Trampolines"); gather_source_objs(); @@ -221,7 +213,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { verify_estimate_size(_estimated_hashtable_bytes, "Hashtables"); - make_trampolines(); + update_method_trampolines(); sort_methods(); log_info(cds)("Make classes shareable"); @@ -254,7 +246,7 @@ size_t DynamicArchiveBuilder::estimate_archive_size() { size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive(); _estimated_hashtable_bytes = symbol_table_est + dictionary_est; - _estimated_trampoline_bytes = estimate_trampoline_size(); + _estimated_trampoline_bytes = allocate_method_trampoline_info(); size_t total = 0; @@ -337,54 +329,6 @@ void DynamicArchiveBuilder::release_header() { _header = NULL; } -size_t DynamicArchiveBuilder::estimate_trampoline_size() { - size_t total = 0; - size_t each_method_bytes = - align_up(SharedRuntime::trampoline_size(), BytesPerWord) + - align_up(sizeof(AdapterHandlerEntry*), BytesPerWord); - - for (int i = 0; i < klasses()->length(); i++) { - Klass* k = klasses()->at(i); - if (k->is_instance_klass()) { - Array* methods = InstanceKlass::cast(k)->methods(); - total += each_method_bytes * methods->length(); - } - } - if (total == 0) { - // We have nothing to archive, but let's avoid having an empty region. - total = SharedRuntime::trampoline_size(); - } - return align_up(total, SharedSpaceObjectAlignment); -} - -void DynamicArchiveBuilder::make_trampolines() { - DumpRegion* mc_space = MetaspaceShared::misc_code_dump_space(); - char* p = mc_space->base(); - for (int i = 0; i < klasses()->length(); i++) { - Klass* k = klasses()->at(i); - if (!k->is_instance_klass()) { - continue; - } - InstanceKlass* ik = InstanceKlass::cast(k); - Array* methods = ik->methods(); - for (int j = 0; j < methods->length(); j++) { - Method* m = methods->at(j); - address c2i_entry_trampoline = (address)p; - p += SharedRuntime::trampoline_size(); - assert(p >= mc_space->base() && p <= mc_space->top(), "must be"); - m->set_from_compiled_entry(to_target(c2i_entry_trampoline)); - - AdapterHandlerEntry** adapter_trampoline =(AdapterHandlerEntry**)p; - p += sizeof(AdapterHandlerEntry*); - assert(p >= mc_space->base() && p <= mc_space->top(), "must be"); - *adapter_trampoline = NULL; - m->set_adapter_trampoline(to_target(adapter_trampoline)); - } - } - - guarantee(p <= mc_space->top(), "Estimate of trampoline size is insufficient"); -} - void DynamicArchiveBuilder::sort_methods() { InstanceKlass::disable_method_binary_search(); for (int i = 0; i < klasses()->length(); i++) { diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index de3ca7ad6cf..ab183ca623d 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -1737,7 +1737,7 @@ address FileMapInfo::decode_start_address(FileMapRegion* spc, bool with_current_ size_t offset = spc->mapping_offset(); narrowOop n = CompressedOops::narrow_oop_cast(offset); if (with_current_oop_encoding_mode) { - return cast_from_oop
(CompressedOops::decode_not_null(n)); + return cast_from_oop
(CompressedOops::decode_raw_not_null(n)); } else { return cast_from_oop
(HeapShared::decode_from_archive(n)); } diff --git a/src/hotspot/share/memory/heapShared.cpp b/src/hotspot/share/memory/heapShared.cpp index 1d9821300f4..9974a5e3b76 100644 --- a/src/hotspot/share/memory/heapShared.cpp +++ b/src/hotspot/share/memory/heapShared.cpp @@ -1150,9 +1150,6 @@ class FindEmbeddedNonNullPointers: public BasicOopIterateClosure { FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap) : _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {} - virtual bool should_verify_oops(void) { - return false; - } virtual void do_oop(narrowOop* p) { _num_total_oops ++; narrowOop v = *p; diff --git a/src/hotspot/share/memory/iterator.hpp b/src/hotspot/share/memory/iterator.hpp index fb3a4c2ca34..98cbd3101ac 100644 --- a/src/hotspot/share/memory/iterator.hpp +++ b/src/hotspot/share/memory/iterator.hpp @@ -102,14 +102,6 @@ class OopIterateClosure : public OopClosure { virtual bool do_metadata() = 0; virtual void do_klass(Klass* k) = 0; virtual void do_cld(ClassLoaderData* cld) = 0; - -#ifdef ASSERT - // Default verification of each visited oop field. - template void verify(T* p); - - // Can be used by subclasses to turn off the default verification of oop fields. - virtual bool should_verify_oops() { return true; } -#endif }; // An OopIterateClosure that can be used when there's no need to visit the Metadata. @@ -357,7 +349,6 @@ class CompareClosure : public Closure { // a concrete implementation, otherwise a virtual call is taken. class Devirtualizer { public: - template static void do_oop_no_verify(OopClosureType* closure, T* p); template static void do_oop(OopClosureType* closure, T* p); template static void do_klass(OopClosureType* closure, Klass* k); template static void do_cld(OopClosureType* closure, ClassLoaderData* cld); diff --git a/src/hotspot/share/memory/iterator.inline.hpp b/src/hotspot/share/memory/iterator.inline.hpp index 5d0300b6d3f..36ee100397d 100644 --- a/src/hotspot/share/memory/iterator.inline.hpp +++ b/src/hotspot/share/memory/iterator.inline.hpp @@ -27,7 +27,6 @@ #include "classfile/classLoaderData.hpp" #include "memory/iterator.hpp" -#include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/klass.hpp" @@ -52,22 +51,6 @@ inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) { ClaimMetadataVisitingOopIterateClosure::do_cld(cld); } -#ifdef ASSERT -// This verification is applied to all visited oops. -// The closures can turn is off by overriding should_verify_oops(). -template -void OopIterateClosure::verify(T* p) { - if (should_verify_oops()) { - T heap_oop = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(heap_oop)) { - oop o = CompressedOops::decode_not_null(heap_oop); - assert(Universe::heap()->is_in(o), - "should be in closed *p " PTR_FORMAT " " PTR_FORMAT, p2i(p), p2i(o)); - } - } -} -#endif - // Implementation of the non-virtual do_oop dispatch. // // The same implementation is used for do_metadata, do_klass, and do_cld. @@ -123,16 +106,9 @@ call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, closure->OopClosureType::do_oop(p); } -template -inline void Devirtualizer::do_oop_no_verify(OopClosureType* closure, T* p) { - call_do_oop(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p); -} - template inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) { - debug_only(closure->verify(p)); - - do_oop_no_verify(closure, p); + call_do_oop(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p); } // Implementation of the non-virtual do_metadata dispatch. diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 0b9328961ff..a28668b5116 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -770,6 +770,9 @@ void VM_PopulateDumpSharedSpace::doit() { builder.relocate_well_known_klasses(); + log_info(cds)("Update method trampolines"); + builder.update_method_trampolines(); + log_info(cds)("Make classes shareable"); builder.make_klasses_shareable(); diff --git a/src/hotspot/share/memory/padded.hpp b/src/hotspot/share/memory/padded.hpp index 08003613609..feca46ac7c2 100644 --- a/src/hotspot/share/memory/padded.hpp +++ b/src/hotspot/share/memory/padded.hpp @@ -116,6 +116,7 @@ template class PaddedPrimitiveArray { public: static T* create_unfreeable(size_t length); + static T* create(size_t length, void** alloc_base); }; #endif // SHARE_MEMORY_PADDED_HPP diff --git a/src/hotspot/share/memory/padded.inline.hpp b/src/hotspot/share/memory/padded.inline.hpp index d698f5ee1b3..742db2fe3f8 100644 --- a/src/hotspot/share/memory/padded.inline.hpp +++ b/src/hotspot/share/memory/padded.inline.hpp @@ -82,11 +82,18 @@ T** Padded2DArray::create_unfreeable(uint rows, uint column template T* PaddedPrimitiveArray::create_unfreeable(size_t length) { + void* temp; + return create(length, &temp); +} + +template +T* PaddedPrimitiveArray::create(size_t length, void** alloc_base) { // Allocate a chunk of memory large enough to allow for some alignment. void* chunk = AllocateHeap(length * sizeof(T) + alignment, flags); memset(chunk, 0, length * sizeof(T) + alignment); + *alloc_base = chunk; return (T*)align_up(chunk, alignment); } diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index c67e9c1c78f..ab5849d6ac7 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -80,6 +80,30 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, _executable = executable; } +// Helper method +static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd) { + if (fd != -1) { + return os::attempt_map_memory_to_file_at(base, size, fd); + } + return os::attempt_reserve_memory_at(base, size); +} + +// Helper method +static char* map_or_reserve_memory(size_t size, int fd) { + if (fd != -1) { + return os::map_memory_to_file(size, fd); + } + return os::reserve_memory(size); +} + +// Helper method +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd) { + if (fd != -1) { + return os::map_memory_to_file_aligned(size, alignment, fd); + } + return os::reserve_memory_aligned(size, alignment); +} + // Helper method static void unmap_or_release_memory(char* base, size_t size, bool is_file_mapped) { if (is_file_mapped) { @@ -188,13 +212,13 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // important. If available space is not detected, return NULL. if (requested_address != 0) { - base = os::attempt_reserve_memory_at(requested_address, size, _fd_for_heap); + base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap); if (failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) { // OS ignored requested address. Try different address. base = NULL; } } else { - base = os::reserve_memory_with_fd(size, _fd_for_heap); + base = map_or_reserve_memory(size, _fd_for_heap); } if (base == NULL) return; @@ -206,7 +230,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // Make sure that size is aligned size = align_up(size, alignment); - base = os::reserve_memory_aligned(size, alignment, _fd_for_heap); + base = map_or_reserve_memory_aligned(size, alignment, _fd_for_heap); if (requested_address != 0 && failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) { @@ -372,13 +396,13 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, } if (requested_address != 0) { - base = os::attempt_reserve_memory_at(requested_address, size, _fd_for_heap); + base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap); } else { // Optimistically assume that the OSes returns an aligned base pointer. // When reserving a large address range, most OSes seem to align to at // least 64K. // If the returned memory is not aligned we will release and retry. - base = os::reserve_memory_with_fd(size, _fd_for_heap); + base = map_or_reserve_memory(size, _fd_for_heap); } } if (base == NULL) { return; } diff --git a/src/hotspot/share/oops/compressedOops.hpp b/src/hotspot/share/oops/compressedOops.hpp index 60f099c9be9..c12f6bd197b 100644 --- a/src/hotspot/share/oops/compressedOops.hpp +++ b/src/hotspot/share/oops/compressedOops.hpp @@ -119,6 +119,7 @@ class CompressedOops : public AllStatic { static bool is_null(oop v) { return v == NULL; } static bool is_null(narrowOop v) { return v == narrowOop::null; } + static inline oop decode_raw_not_null(narrowOop v); static inline oop decode_raw(narrowOop v); static inline oop decode_not_null(narrowOop v); static inline oop decode(narrowOop v); @@ -126,10 +127,10 @@ class CompressedOops : public AllStatic { static inline narrowOop encode(oop v); // No conversions needed for these overloads - static oop decode_not_null(oop v) { return v; } - static oop decode(oop v) { return v; } - static narrowOop encode_not_null(narrowOop v) { return v; } - static narrowOop encode(narrowOop v) { return v; } + static inline oop decode_not_null(oop v); + static inline oop decode(oop v); + static inline narrowOop encode_not_null(narrowOop v); + static inline narrowOop encode(narrowOop v); static inline uint32_t narrow_oop_value(oop o); static inline uint32_t narrow_oop_value(narrowOop o); diff --git a/src/hotspot/share/oops/compressedOops.inline.hpp b/src/hotspot/share/oops/compressedOops.inline.hpp index 8c8a922094d..920e87703b4 100644 --- a/src/hotspot/share/oops/compressedOops.inline.hpp +++ b/src/hotspot/share/oops/compressedOops.inline.hpp @@ -41,6 +41,11 @@ // offset from the heap base. Saving the check for null can save instructions // in inner GC loops so these are separated. +inline oop CompressedOops::decode_raw_not_null(narrowOop v) { + assert(!is_null(v), "narrow oop value can never be zero"); + return decode_raw(v); +} + inline oop CompressedOops::decode_raw(narrowOop v) { return (oop)(void*)((uintptr_t)base() + ((uintptr_t)v << shift())); } @@ -49,6 +54,7 @@ inline oop CompressedOops::decode_not_null(narrowOop v) { assert(!is_null(v), "narrow oop value can never be zero"); oop result = decode_raw(v); assert(is_object_aligned(result), "address not aligned: " INTPTR_FORMAT, p2i((void*) result)); + assert(Universe::heap()->is_in(result), "object not in heap " PTR_FORMAT, p2i((void*) result)); return result; } @@ -63,7 +69,7 @@ inline narrowOop CompressedOops::encode_not_null(oop v) { uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base(), 1)); assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); narrowOop result = narrow_oop_cast(pd >> shift()); - assert(decode(result) == v, "reversibility"); + assert(decode_raw(result) == v, "reversibility"); return result; } @@ -71,6 +77,24 @@ inline narrowOop CompressedOops::encode(oop v) { return is_null(v) ? narrowOop::null : encode_not_null(v); } +inline oop CompressedOops::decode_not_null(oop v) { + assert(Universe::heap()->is_in(v), "object not in heap " PTR_FORMAT, p2i((void*) v)); + return v; +} + +inline oop CompressedOops::decode(oop v) { + assert(Universe::heap()->is_in_or_null(v), "object not in heap " PTR_FORMAT, p2i((void*) v)); + return v; +} + +inline narrowOop CompressedOops::encode_not_null(narrowOop v) { + return v; +} + +inline narrowOop CompressedOops::encode(narrowOop v) { + return v; +} + inline uint32_t CompressedOops::narrow_oop_value(oop o) { return narrow_oop_value(encode(o)); } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 32e35546de5..c0c5c52feac 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1107,17 +1107,9 @@ void Method::unlink_method() { _i2i_entry = Interpreter::entry_for_cds_method(methodHandle(Thread::current(), this)); _from_interpreted_entry = _i2i_entry; - if (DynamicDumpSharedSpaces) { - assert(_from_compiled_entry != NULL, "sanity"); - } else { - // TODO: Simplify the adapter trampoline allocation for static archiving. - // Remove the use of CDSAdapterHandlerEntry. - CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter(); - constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline()); - _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline(); - assert(*((int*)_from_compiled_entry) == 0, - "must be NULL during dump time, to be initialized at run time"); - } + assert(_from_compiled_entry != NULL, "sanity"); + assert(*((int*)_from_compiled_entry) == 0, + "must be NULL during dump time, to be initialized at run time"); if (is_native()) { *native_function_addr() = NULL; diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index f318dd6a3db..4688b01d534 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -716,8 +716,6 @@ class CallStaticJavaNode : public CallJavaNode { init_flags(Flag_is_macro); C->add_macro_node(this); } - _is_scalar_replaceable = false; - _is_non_escaping = false; } CallStaticJavaNode(const TypeFunc* tf, address addr, const char* name, int bci, const TypePtr* adr_type) @@ -725,15 +723,9 @@ class CallStaticJavaNode : public CallJavaNode { init_class_id(Class_CallStaticJava); // This node calls a runtime stub, which often has narrow memory effects. _adr_type = adr_type; - _is_scalar_replaceable = false; - _is_non_escaping = false; _name = name; } - // Result of Escape Analysis - bool _is_scalar_replaceable; - bool _is_non_escaping; - // If this is an uncommon trap, return the request code, else zero. int uncommon_trap_request() const; static int extract_uncommon_trap_request(const Node* call); diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index f01687ebb2c..39a375f027a 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -929,8 +929,6 @@ void Compile::Init(int aliaslevel) { set_max_inline_size(MaxInlineSize); set_freq_inline_size(FreqInlineSize); set_do_scheduling(OptoScheduling); - set_do_count_invocations(false); - set_do_method_data_update(false); set_do_vector_loop(false); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 615279aa116..46c4dcfb9c6 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -282,8 +282,6 @@ class Compile : public Phase { bool _do_inlining; // True if we intend to do inlining bool _do_scheduling; // True if we intend to do scheduling bool _do_freq_based_layout; // True if we intend to do frequency based block layout - bool _do_count_invocations; // True if we generate code to count invocations - bool _do_method_data_update; // True if we generate code to update MethodData*s bool _do_vector_loop; // True if allowed to execute loop in parallel iterations bool _use_cmove; // True if CMove should be used without profitability analysis bool _age_code; // True if we need to profile code age (decrement the aging counter) @@ -571,10 +569,6 @@ class Compile : public Phase { void set_do_scheduling(bool z) { _do_scheduling = z; } bool do_freq_based_layout() const{ return _do_freq_based_layout; } void set_do_freq_based_layout(bool z){ _do_freq_based_layout = z; } - bool do_count_invocations() const{ return _do_count_invocations; } - void set_do_count_invocations(bool z){ _do_count_invocations = z; } - bool do_method_data_update() const { return _do_method_data_update; } - void set_do_method_data_update(bool z) { _do_method_data_update = z; } bool do_vector_loop() const { return _do_vector_loop; } void set_do_vector_loop(bool z) { _do_vector_loop = z; } bool use_cmove() const { return _use_cmove; } diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index 7dba7b65dff..13053bb6317 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -643,10 +643,6 @@ void Parse::do_call() { receiver = record_profiled_receiver_for_speculation(receiver); } - // Bump method data counters (We profile *before* the call is made - // because exceptions don't return to the call site.) - profile_call(receiver); - JVMState* new_jvms = cg->generate(jvms); if (new_jvms == NULL) { // When inlining attempt fails (e.g., too many arguments), diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index da5590bf0f0..5742f4e862b 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -246,9 +246,6 @@ bool ConnectionGraph::compute_escape() { if (n->is_Allocate()) { n->as_Allocate()->_is_non_escaping = noescape; } - if (n->is_CallStaticJava()) { - n->as_CallStaticJava()->_is_non_escaping = noescape; - } if (noescape && ptn->scalar_replaceable()) { adjust_scalar_replaceable_state(ptn); if (ptn->scalar_replaceable()) { @@ -3068,11 +3065,6 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, // so it could be eliminated if it has no uses. alloc->as_Allocate()->_is_scalar_replaceable = true; } - if (alloc->is_CallStaticJava()) { - // Set the scalar_replaceable flag for boxing method - // so it could be eliminated if it has no uses. - alloc->as_CallStaticJava()->_is_scalar_replaceable = true; - } continue; } if (!n->is_CheckCastPP()) { // not unique CheckCastPP. @@ -3121,11 +3113,6 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, // so it could be eliminated. alloc->as_Allocate()->_is_scalar_replaceable = true; } - if (alloc->is_CallStaticJava()) { - // Set the scalar_replaceable flag for boxing method - // so it could be eliminated. - alloc->as_CallStaticJava()->_is_scalar_replaceable = true; - } set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state // in order for an object to be scalar-replaceable, it must be: // - a direct allocation (not a call returning an object) diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 8a374d0d15d..8ab78ce620d 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1045,16 +1045,6 @@ void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLo } } -//------------------------------policy_align----------------------------------- -// Return TRUE or FALSE if the loop should be cache-line aligned. Gather the -// expression that does the alignment. Note that only one array base can be -// aligned in a loop (unless the VM guarantees mutual alignment). Note that -// if we vectorize short memory ops into longer memory ops, we may want to -// increase alignment. -bool IdealLoopTree::policy_align(PhaseIdealLoop *phase) const { - return false; -} - //------------------------------policy_range_check----------------------------- // Return TRUE or FALSE if the loop should be range-check-eliminated or not. // When TRUE, the estimated node budget is also requested. @@ -3341,9 +3331,8 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n uint est_peeling = estimate_peeling(phase); bool should_peel = 0 < est_peeling; - // Counted loops may be peeled, may need some iterations run up - // front for RCE, and may want to align loop refs to a cache - // line. Thus we clone a full loop up front whose trip count is + // Counted loops may be peeled, or may need some iterations run up + // front for RCE. Thus we clone a full loop up front whose trip count is // at least 1 (if peeling), but may be several more. // The main loop will start cache-line aligned with at least 1 @@ -3355,27 +3344,25 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n bool should_unroll = policy_unroll(phase); bool should_rce = policy_range_check(phase); - // TODO: Remove align -- not used. - bool should_align = policy_align(phase); - // If not RCE'ing (iteration splitting) or Aligning, then we do not need a - // pre-loop. We may still need to peel an initial iteration but we will not + // If not RCE'ing (iteration splitting), then we do not need a pre-loop. + // We may still need to peel an initial iteration but we will not // be needing an unknown number of pre-iterations. // - // Basically, if may_rce_align reports FALSE first time through, we will not - // be able to later do RCE or Aligning on this loop. - bool may_rce_align = !policy_peel_only(phase) || should_rce || should_align; + // Basically, if peel_only reports TRUE first time through, we will not + // be able to later do RCE on this loop. + bool peel_only = policy_peel_only(phase) && !should_rce; - // If we have any of these conditions (RCE, alignment, unrolling) met, then + // If we have any of these conditions (RCE, unrolling) met, then // we switch to the pre-/main-/post-loop model. This model also covers // peeling. - if (should_rce || should_align || should_unroll) { + if (should_rce || should_unroll) { if (cl->is_normal_loop()) { // Convert to 'pre/main/post' loops uint estimate = est_loop_clone_sz(3); if (!phase->may_require_nodes(estimate)) { return false; } - phase->insert_pre_post_loops(this, old_new, !may_rce_align); + phase->insert_pre_post_loops(this, old_new, peel_only); } // Adjust the pre- and main-loop limits to let the pre and post loops run // with full checks, but the main-loop with no checks. Remove said checks @@ -3406,11 +3393,6 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n } phase->do_unroll(this, old_new, true); } - - // Adjust the pre-loop limits to align the main body iterations. - if (should_align) { - Unimplemented(); - } } else { // Else we have an unchanged counted loop if (should_peel) { // Might want to peel but do nothing else if (phase->may_require_nodes(est_peeling)) { diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index ab6f783978f..ac65ffc09ed 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -617,13 +617,6 @@ class IdealLoopTree : public ResourceObj { // also gather the end of the first split and the start of the 2nd split. bool policy_range_check( PhaseIdealLoop *phase ) const; - // Return TRUE or FALSE if the loop should be cache-line aligned. - // Gather the expression that does the alignment. Note that only - // one array base can be aligned in a loop (unless the VM guarantees - // mutual alignment). Note that if we vectorize short memory ops - // into longer memory ops, we may want to increase alignment. - bool policy_align( PhaseIdealLoop *phase ) const; - // Return TRUE if "iff" is a range check. bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const; diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index f288225c0ba..09bb0fcd2c0 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -1268,6 +1268,59 @@ Node* LoadNode::convert_to_signed_load(PhaseGVN& gvn) { is_unaligned_access(), is_mismatched_access()); } +bool LoadNode::has_reinterpret_variant(const Type* rt) { + BasicType bt = rt->basic_type(); + switch (Opcode()) { + case Op_LoadI: return (bt == T_FLOAT); + case Op_LoadL: return (bt == T_DOUBLE); + case Op_LoadF: return (bt == T_INT); + case Op_LoadD: return (bt == T_LONG); + + default: return false; + } +} + +Node* LoadNode::convert_to_reinterpret_load(PhaseGVN& gvn, const Type* rt) { + BasicType bt = rt->basic_type(); + assert(has_reinterpret_variant(rt), "no reinterpret variant: %s %s", Name(), type2name(bt)); + bool is_mismatched = is_mismatched_access(); + const TypeRawPtr* raw_type = gvn.type(in(MemNode::Memory))->isa_rawptr(); + if (raw_type == NULL) { + is_mismatched = true; // conservatively match all non-raw accesses as mismatched + } + return LoadNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), + raw_adr_type(), rt, bt, _mo, _control_dependency, + is_unaligned_access(), is_mismatched); +} + +bool StoreNode::has_reinterpret_variant(const Type* vt) { + BasicType bt = vt->basic_type(); + switch (Opcode()) { + case Op_StoreI: return (bt == T_FLOAT); + case Op_StoreL: return (bt == T_DOUBLE); + case Op_StoreF: return (bt == T_INT); + case Op_StoreD: return (bt == T_LONG); + + default: return false; + } +} + +Node* StoreNode::convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Type* vt) { + BasicType bt = vt->basic_type(); + assert(has_reinterpret_variant(vt), "no reinterpret variant: %s %s", Name(), type2name(bt)); + StoreNode* st = StoreNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), val, bt, _mo); + + bool is_mismatched = is_mismatched_access(); + const TypeRawPtr* raw_type = gvn.type(in(MemNode::Memory))->isa_rawptr(); + if (raw_type == NULL) { + is_mismatched = true; // conservatively match all non-raw accesses as mismatched + } + if (is_mismatched) { + st->set_mismatched_access(); + } + return st; +} + // We're loading from an object which has autobox behaviour. // If this object is result of a valueOf call we'll have a phi // merging a newly allocated object and a load from the cache. @@ -2548,6 +2601,7 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* mem = in(MemNode::Memory); Node* address = in(MemNode::Address); + Node* value = in(MemNode::ValueIn); // Back-to-back stores to same address? Fold em up. Generally // unsafe if I have intervening uses... Also disallowed for StoreCM // since they must follow each StoreP operation. Redundant StoreCMs @@ -2611,6 +2665,19 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) { } } + // Fold reinterpret cast into memory operation: + // StoreX mem (MoveY2X v) => StoreY mem v + if (value->is_Move()) { + const Type* vt = value->in(1)->bottom_type(); + if (has_reinterpret_variant(vt)) { + if (phase->C->post_loop_opts_phase()) { + return convert_to_reinterpret_store(*phase, value->in(1), vt); + } else { + phase->C->record_for_post_loop_opts_igvn(this); // attempt the transformation once loop opts are over + } + } + } + return NULL; // No further progress } diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 413c64e7604..8899a8f48f6 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -282,6 +282,9 @@ class LoadNode : public MemNode { Node* convert_to_unsigned_load(PhaseGVN& gvn); Node* convert_to_signed_load(PhaseGVN& gvn); + bool has_reinterpret_variant(const Type* rt); + Node* convert_to_reinterpret_load(PhaseGVN& gvn, const Type* rt); + void pin() { _control_dependency = Pinned; } bool has_unknown_control_dependency() const { return _control_dependency == UnknownControl; } @@ -634,6 +637,9 @@ class StoreNode : public MemNode { // have all possible loads of the value stored been optimized away? bool value_never_loaded(PhaseTransform *phase) const; + bool has_reinterpret_variant(const Type* vt); + Node* convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Type* vt); + MemBarNode* trailing_membar() const; }; diff --git a/src/hotspot/share/opto/movenode.cpp b/src/hotspot/share/opto/movenode.cpp index ad550a7b078..f5a001d6648 100644 --- a/src/hotspot/share/opto/movenode.cpp +++ b/src/hotspot/share/opto/movenode.cpp @@ -352,6 +352,36 @@ Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) { return abs; } +//------------------------------MoveNode------------------------------------------ + +Node* MoveNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (can_reshape) { + // Fold reinterpret cast into memory operation: + // MoveX2Y (LoadX mem) => LoadY mem + LoadNode* ld = in(1)->isa_Load(); + if (ld != NULL && (ld->outcnt() == 1)) { // replace only + const Type* rt = bottom_type(); + if (ld->has_reinterpret_variant(rt)) { + if (phase->C->post_loop_opts_phase()) { + return ld->convert_to_reinterpret_load(*phase, rt); + } else { + phase->C->record_for_post_loop_opts_igvn(this); // attempt the transformation once loop opts are over + } + } + } + } + return NULL; +} + +Node* MoveNode::Identity(PhaseGVN* phase) { + if (in(1)->is_Move()) { + // Back-to-back moves: MoveX2Y (MoveY2X v) => v + assert(bottom_type() == in(1)->in(1)->bottom_type(), "sanity"); + return in(1)->in(1); + } + return this; +} + //------------------------------Value------------------------------------------ const Type* MoveL2DNode::Value(PhaseGVN* phase) const { const Type *t = phase->type( in(1) ); diff --git a/src/hotspot/share/opto/movenode.hpp b/src/hotspot/share/opto/movenode.hpp index 323cd7cc5d1..1e8b1b2489b 100644 --- a/src/hotspot/share/opto/movenode.hpp +++ b/src/hotspot/share/opto/movenode.hpp @@ -98,41 +98,52 @@ class CMoveNNode : public CMoveNode { }; // -class MoveI2FNode : public Node { +class MoveNode : public Node { + protected: + MoveNode(Node* value) : Node(NULL, value) { + init_class_id(Class_Move); + } + + public: + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual Node* Identity(PhaseGVN* phase); +}; + +class MoveI2FNode : public MoveNode { public: - MoveI2FNode( Node *value ) : Node(0,value) {} + MoveI2FNode(Node* value) : MoveNode(value) {} virtual int Opcode() const; - virtual const Type *bottom_type() const { return Type::FLOAT; } + virtual const Type* bottom_type() const { return Type::FLOAT; } virtual uint ideal_reg() const { return Op_RegF; } virtual const Type* Value(PhaseGVN* phase) const; virtual Node* Identity(PhaseGVN* phase); }; -class MoveL2DNode : public Node { +class MoveL2DNode : public MoveNode { public: - MoveL2DNode( Node *value ) : Node(0,value) {} + MoveL2DNode(Node* value) : MoveNode(value) {} virtual int Opcode() const; - virtual const Type *bottom_type() const { return Type::DOUBLE; } + virtual const Type* bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type* Value(PhaseGVN* phase) const; virtual Node* Identity(PhaseGVN* phase); }; -class MoveF2INode : public Node { +class MoveF2INode : public MoveNode { public: - MoveF2INode( Node *value ) : Node(0,value) {} + MoveF2INode(Node* value) : MoveNode(value) {} virtual int Opcode() const; - virtual const Type *bottom_type() const { return TypeInt::INT; } + virtual const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } virtual const Type* Value(PhaseGVN* phase) const; virtual Node* Identity(PhaseGVN* phase); }; -class MoveD2LNode : public Node { +class MoveD2LNode : public MoveNode { public: - MoveD2LNode( Node *value ) : Node(0,value) {} + MoveD2LNode(Node* value) : MoveNode(value) {} virtual int Opcode() const; - virtual const Type *bottom_type() const { return TypeLong::LONG; } + virtual const Type* bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } virtual const Type* Value(PhaseGVN* phase) const; virtual Node* Identity(PhaseGVN* phase); diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index fc2d7e81d41..7dc59465a5e 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -112,6 +112,7 @@ class MemBarNode; class MemBarStoreStoreNode; class MemNode; class MergeMemNode; +class MoveNode; class MulNode; class MultiNode; class MultiBranchNode; @@ -721,10 +722,11 @@ class Node { DEFINE_CLASS_ID(Vector, Node, 13) DEFINE_CLASS_ID(VectorMaskCmp, Vector, 0) DEFINE_CLASS_ID(ClearArray, Node, 14) - DEFINE_CLASS_ID(Halt, Node, 15) - DEFINE_CLASS_ID(Opaque1, Node, 16) + DEFINE_CLASS_ID(Halt, Node, 15) + DEFINE_CLASS_ID(Opaque1, Node, 16) + DEFINE_CLASS_ID(Move, Node, 17) - _max_classes = ClassMask_Opaque1 + _max_classes = ClassMask_Move }; #undef DEFINE_CLASS_ID @@ -870,6 +872,7 @@ class Node { DEFINE_CLASS_QUERY(MemBar) DEFINE_CLASS_QUERY(MemBarStoreStore) DEFINE_CLASS_QUERY(MergeMem) + DEFINE_CLASS_QUERY(Move) DEFINE_CLASS_QUERY(Mul) DEFINE_CLASS_QUERY(Multi) DEFINE_CLASS_QUERY(MultiBranch) diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index a6e7703796a..6166ede33cc 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -330,8 +330,6 @@ class Parse : public GraphKit { bool _wrote_volatile; // Did we write a volatile field? bool _wrote_stable; // Did we write a @Stable field? bool _wrote_fields; // Did we write any field? - bool _count_invocations; // update and test invocation counter - bool _method_data_update; // update method data oop Node* _alloc_with_final; // An allocation node with final field // Variables which track Java semantics during bytecode parsing: @@ -377,8 +375,6 @@ class Parse : public GraphKit { void set_wrote_stable(bool z) { _wrote_stable = z; } bool wrote_fields() const { return _wrote_fields; } void set_wrote_fields(bool z) { _wrote_fields = z; } - bool count_invocations() const { return _count_invocations; } - bool method_data_update() const { return _method_data_update; } Node* alloc_with_final() const { return _alloc_with_final; } void set_alloc_with_final(Node* n) { assert((_alloc_with_final == NULL) || (_alloc_with_final == n), "different init objects?"); @@ -500,9 +496,6 @@ class Parse : public GraphKit { // Helper function to uncommon-trap or bailout for non-compilable call-sites bool can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass *klass); - // Helper function to setup for type-profile based inlining - bool prepare_type_profile_inline(ciInstanceKlass* prof_klass, ciMethod* prof_method); - // Helper functions for type checking bytecodes: void do_checkcast(); void do_instanceof(); @@ -555,9 +548,9 @@ class Parse : public GraphKit { void maybe_add_predicate_after_if(Block* path); IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt); Node* jump_if_join(Node* iffalse, Node* iftrue); - void jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, int prof_table_index, bool unc); - void jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, int prof_table_index, bool unc); - void jump_if_always_fork(int dest_bci_if_true, int prof_table_index, bool unc); + void jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, bool unc); + void jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, bool unc); + void jump_if_always_fork(int dest_bci_if_true, bool unc); friend class SwitchRange; void do_tableswitch(); @@ -567,23 +560,6 @@ class Parse : public GraphKit { void linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchRange*& hi); void decrement_age(); - // helper functions for methodData style profiling - void test_counter_against_threshold(Node* cnt, int limit); - void increment_and_test_invocation_counter(int limit); - void test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize offset, int limit); - Node* method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize offset, Node* idx = NULL, uint stride = 0); - void increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize offset, Node* idx = NULL, uint stride = 0); - void set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_constant); - - void profile_method_entry(); - void profile_taken_branch(int target_bci, bool force_update = false); - void profile_not_taken_branch(bool force_update = false); - void profile_call(Node* receiver); - void profile_generic_call(); - void profile_receiver_type(Node* receiver); - void profile_ret(int target_bci); - void profile_null_checkcast(); - void profile_switch_case(int table_index); // helper function for call statistics void count_compiled_calls(bool at_method_entry, bool is_inline) PRODUCT_RETURN; diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index baf2bf9bacc..73f1c4ab000 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -483,9 +483,6 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) // Accumulate total sum of decompilations, also. C->set_decompile_count(C->decompile_count() + md->decompile_count()); - _count_invocations = C->do_count_invocations(); - _method_data_update = C->do_method_data_update(); - if (log != NULL && method()->has_exception_handlers()) { log->elem("observe that='has_exception_handlers'"); } @@ -1228,10 +1225,6 @@ void Parse::do_method_entry() { // Feed profiling data for parameters to the type system so it can // propagate it as speculative types record_profiled_parameters_for_speculation(); - - if (depth() == 1) { - increment_and_test_invocation_counter(Tier2CompileThreshold); - } } //------------------------------init_blocks------------------------------------ diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 59e9ce7a9dd..d39e0456388 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -232,7 +232,7 @@ Node* Parse::jump_if_join(Node* iffalse, Node* iftrue) { static const int never_reached = INT_MAX; //------------------------------helper for tableswitch------------------------- -void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) { +void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, bool unc) { // True branch, use existing map info { PreserveJVMState pjvms(this); Node *iftrue = _gvn.transform( new IfTrueNode (iff) ); @@ -245,7 +245,6 @@ void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_ "taken always"); } else { assert(dest_bci_if_true != never_reached, "inconsistent dest"); - profile_switch_case(prof_table_index); merge_new_path(dest_bci_if_true); } } @@ -255,7 +254,7 @@ void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_ set_control( iffalse ); } -void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) { +void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, bool unc) { // True branch, use existing map info { PreserveJVMState pjvms(this); Node *iffalse = _gvn.transform( new IfFalseNode (iff) ); @@ -268,7 +267,6 @@ void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table "taken never"); } else { assert(dest_bci_if_true != never_reached, "inconsistent dest"); - profile_switch_case(prof_table_index); merge_new_path(dest_bci_if_true); } } @@ -278,7 +276,7 @@ void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table set_control( iftrue ); } -void Parse::jump_if_always_fork(int dest_bci, int prof_table_index, bool unc) { +void Parse::jump_if_always_fork(int dest_bci, bool unc) { // False branch, use existing map and control() if (unc) { repush_if_args(); @@ -288,7 +286,6 @@ void Parse::jump_if_always_fork(int dest_bci, int prof_table_index, bool unc) { "taken never"); } else { assert(dest_bci != never_reached, "inconsistent dest"); - profile_switch_case(prof_table_index); merge_new_path(dest_bci); } } @@ -303,34 +300,28 @@ extern "C" { } -// Default value for methodData switch indexing. Must be a negative value to avoid -// conflict with any legal switch index. -#define NullTableIndex -1 - class SwitchRange : public StackObj { // a range of integers coupled with a bci destination jint _lo; // inclusive lower limit jint _hi; // inclusive upper limit int _dest; - int _table_index; // index into method data table float _cnt; // how many times this range was hit according to profiling public: jint lo() const { return _lo; } jint hi() const { return _hi; } int dest() const { return _dest; } - int table_index() const { return _table_index; } bool is_singleton() const { return _lo == _hi; } float cnt() const { return _cnt; } - void setRange(jint lo, jint hi, int dest, int table_index, float cnt) { + void setRange(jint lo, jint hi, int dest, float cnt) { assert(lo <= hi, "must be a non-empty range"); - _lo = lo, _hi = hi; _dest = dest; _table_index = table_index; _cnt = cnt; + _lo = lo, _hi = hi; _dest = dest; _cnt = cnt; assert(_cnt >= 0, ""); } - bool adjoinRange(jint lo, jint hi, int dest, int table_index, float cnt, bool trim_ranges) { + bool adjoinRange(jint lo, jint hi, int dest, float cnt, bool trim_ranges) { assert(lo <= hi, "must be a non-empty range"); - if (lo == _hi+1 && table_index == _table_index) { + if (lo == _hi+1) { // see merge_ranges() comment below if (trim_ranges) { if (cnt == 0) { @@ -360,14 +351,14 @@ class SwitchRange : public StackObj { return false; } - void set (jint value, int dest, int table_index, float cnt) { - setRange(value, value, dest, table_index, cnt); + void set (jint value, int dest, float cnt) { + setRange(value, value, dest, cnt); } - bool adjoin(jint value, int dest, int table_index, float cnt, bool trim_ranges) { - return adjoinRange(value, value, dest, table_index, cnt, trim_ranges); + bool adjoin(jint value, int dest, float cnt, bool trim_ranges) { + return adjoinRange(value, value, dest, cnt, trim_ranges); } bool adjoin(SwitchRange& other) { - return adjoinRange(other._lo, other._hi, other._dest, other._table_index, other._cnt, false); + return adjoinRange(other._lo, other._hi, other._dest, other._cnt, false); } void print() { @@ -418,7 +409,7 @@ static void merge_ranges(SwitchRange* ranges, int& rp) { for (int j = 0; j <= rp; j++) { SwitchRange& r = ranges[j]; if (r.cnt() == 0 && r.dest() != never_reached) { - r.setRange(r.lo(), r.hi(), never_reached, r.table_index(), r.cnt()); + r.setRange(r.lo(), r.hi(), never_reached, r.cnt()); } } } @@ -447,7 +438,7 @@ void Parse::do_tableswitch() { profile = (ciMultiBranchData*)data; } } - bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); + bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); // generate decision tree, using trichotomy when possible int rnum = len+2; @@ -459,19 +450,18 @@ void Parse::do_tableswitch() { if (profile != NULL) { cnt = profile->default_count() / (hi_index != max_jint ? 2 : 1); } - ranges[++rp].setRange(min_jint, lo_index-1, default_dest, NullTableIndex, cnt); + ranges[++rp].setRange(min_jint, lo_index-1, default_dest, cnt); } for (int j = 0; j < len; j++) { jint match_int = lo_index+j; int dest = iter().get_dest_table(j+3); makes_backward_branch |= (dest <= bci()); - int table_index = method_data_update() ? j : NullTableIndex; uint cnt = 1; if (profile != NULL) { cnt = profile->count_at(j); } - if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) { - ranges[++rp].set(match_int, dest, table_index, cnt); + if (rp < 0 || !ranges[rp].adjoin(match_int, dest, cnt, trim_ranges)) { + ranges[++rp].set(match_int, dest, cnt); } } jint highest = lo_index+(len-1); @@ -481,8 +471,8 @@ void Parse::do_tableswitch() { if (profile != NULL) { cnt = profile->default_count() / (lo_index != min_jint ? 2 : 1); } - if (!ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, cnt, trim_ranges)) { - ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, cnt); + if (!ranges[rp].adjoinRange(highest+1, max_jint, default_dest, cnt, trim_ranges)) { + ranges[++rp].setRange(highest+1, max_jint, default_dest, cnt); } } assert(rp < len+2, "not too many ranges"); @@ -520,7 +510,7 @@ void Parse::do_lookupswitch() { profile = (ciMultiBranchData*)data; } } - bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); + bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); // generate decision tree, using trichotomy when possible jint* table = NEW_RESOURCE_ARRAY(jint, len*3); @@ -560,23 +550,22 @@ void Parse::do_lookupswitch() { int dest = table[3*j+1]; int cnt = table[3*j+2]; int next_lo = rp < 0 ? min_jint : ranges[rp].hi()+1; - int table_index = method_data_update() ? j : NullTableIndex; makes_backward_branch |= (dest <= bci()); float c = default_cnt * ((float)match_int - next_lo); - if (match_int != next_lo && (rp < 0 || !ranges[rp].adjoinRange(next_lo, match_int-1, default_dest, NullTableIndex, c, trim_ranges))) { + if (match_int != next_lo && (rp < 0 || !ranges[rp].adjoinRange(next_lo, match_int-1, default_dest, c, trim_ranges))) { assert(default_dest != never_reached, "sentinel value for dead destinations"); - ranges[++rp].setRange(next_lo, match_int-1, default_dest, NullTableIndex, c); + ranges[++rp].setRange(next_lo, match_int-1, default_dest, c); } - if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) { + if (rp < 0 || !ranges[rp].adjoin(match_int, dest, cnt, trim_ranges)) { assert(dest != never_reached, "sentinel value for dead destinations"); - ranges[++rp].set(match_int, dest, table_index, cnt); + ranges[++rp].set(match_int, dest, cnt); } } jint highest = table[3*(len-1)]; assert(ranges[rp].hi() == highest, ""); if (highest != max_jint && - !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest), trim_ranges)) { - ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest)); + !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, default_cnt * ((float)max_jint - highest), trim_ranges)) { + ranges[++rp].setRange(highest+1, max_jint, default_dest, default_cnt * ((float)max_jint - highest)); } assert(rp < rnum, "not too many ranges"); @@ -735,7 +724,7 @@ void Parse::linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchR shift++; if (i > 0 && i < nr-1) { SwitchRange prev = lo[i-1]; - prev.setRange(prev.lo(), sr->hi(), prev.dest(), prev.table_index(), prev.cnt()); + prev.setRange(prev.lo(), sr->hi(), prev.dest(), prev.cnt()); if (prev.adjoin(lo[i+1])) { shift++; i++; @@ -762,7 +751,7 @@ void Parse::linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchR Node* cmp = _gvn.transform(new CmpUNode(val, _gvn.intcon(most_freq.hi() - most_freq.lo()))); Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::le)); IfNode* iff = create_and_map_if(control(), tst, if_prob(most_freq.cnt(), total_cnt), if_cnt(most_freq.cnt())); - jump_if_true_fork(iff, most_freq.dest(), most_freq.table_index(), false); + jump_if_true_fork(iff, most_freq.dest(), false); sub += most_freq.cnt() / total_cnt; extra += 1 - sub; @@ -778,9 +767,6 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) // Are jumptables supported if (!Matcher::has_match_rule(Op_Jump)) return false; - // Don't make jump table if profiling - if (method_data_update()) return false; - bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); // Decide if a guard is needed to lop off big ranges at either (or @@ -858,7 +844,7 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) Node* cmp = _gvn.transform(new CmpUNode(key_val, size)); Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::ge)); IfNode* iff = create_and_map_if(control(), tst, if_prob(trimmed_cnt, total), if_cnt(trimmed_cnt)); - jump_if_true_fork(iff, default_dest, NullTableIndex, trim_ranges && trimmed_cnt == 0); + jump_if_true_fork(iff, default_dest, trim_ranges && trimmed_cnt == 0); total -= trimmed_cnt; } @@ -918,7 +904,7 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) { PreserveJVMState pjvms(this); set_control(input); - jump_if_always_fork(r->dest(), r->table_index(), trim_ranges && r->cnt() == 0); + jump_if_always_fork(r->dest(), trim_ranges && r->cnt() == 0); } } } @@ -930,7 +916,7 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) //----------------------------jump_switch_ranges------------------------------- void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, int switch_depth) { Block* switch_block = block(); - bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); + bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if); if (switch_depth == 0) { // Do special processing for the top-level call. @@ -971,13 +957,13 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, lo++; } if (lo->lo() < min_val) { - lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index(), lo->cnt()); + lo->setRange(min_val, lo->hi(), lo->dest(), lo->cnt()); } while (hi->lo() > max_val) { hi--; } if (hi->hi() > max_val) { - hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index(), hi->cnt()); + hi->setRange(hi->lo(), max_val, hi->dest(), hi->cnt()); } linear_search_switch_ranges(key_val, lo, hi); @@ -992,7 +978,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, assert(lo <= hi, "must be a non-empty set of ranges"); if (lo == hi) { - jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0); + jump_if_always_fork(lo->dest(), trim_ranges && lo->cnt() == 0); } else { assert(lo->hi() == (lo+1)->lo()-1, "contiguous ranges"); assert(hi->lo() == (hi-1)->hi()+1, "contiguous ranges"); @@ -1030,7 +1016,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, if (mid->is_singleton()) { IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne, 1-if_prob(mid->cnt(), total_cnt), if_cnt(mid->cnt())); - jump_if_false_fork(iff_ne, mid->dest(), mid->table_index(), trim_ranges && mid->cnt() == 0); + jump_if_false_fork(iff_ne, mid->dest(), trim_ranges && mid->cnt() == 0); // Special Case: If there are exactly three ranges, and the high // and low range each go to the same place, omit the "gt" test, @@ -1059,7 +1045,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, // if there is a higher range, test for it and process it: if (mid == hi) { - jump_if_true_fork(iff_ge, mid->dest(), mid->table_index(), trim_ranges && cnt == 0); + jump_if_true_fork(iff_ge, mid->dest(), trim_ranges && cnt == 0); } else { Node *iftrue = _gvn.transform( new IfTrueNode(iff_ge) ); Node *iffalse = _gvn.transform( new IfFalseNode(iff_ge) ); @@ -1076,7 +1062,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, if (mid->is_singleton()) { jump_switch_ranges(key_val, lo+1, hi, switch_depth+1); } else { - jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0); + jump_if_always_fork(lo->dest(), trim_ranges && lo->cnt() == 0); } } else { jump_switch_ranges(key_val, lo, mid-1, switch_depth+1); @@ -1211,9 +1197,6 @@ void Parse::do_jsr() { int return_bci = iter().next_bci(); int jsr_bci = (bc() == Bytecodes::_jsr) ? iter().get_dest() : iter().get_far_dest(); - // Update method data - profile_taken_branch(jsr_bci); - // The way we do things now, there is only one successor block // for the jsr, because the target code is cloned by ciTypeFlow. Block* target = successor_for_bci(jsr_bci); @@ -1235,7 +1218,6 @@ void Parse::do_ret() { assert(block()->num_successors() == 1, "a ret can only go one place now"); Block* target = block()->successor_at(0); assert(!target->is_ready(), "our arrival must be expected"); - profile_ret(target->flow()->start()); int pnum = target->next_path_num(); merge_common(target, pnum); } @@ -1447,11 +1429,6 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { tty->print_cr("Never-taken edge stops compilation at bci %d", bci()); } repush_if_args(); // to gather stats on loop - // We need to mark this branch as taken so that if we recompile we will - // see that it is possible. In the tiered system the interpreter doesn't - // do profiling and by the time we get to the lower tier from the interpreter - // the path may be cold again. Make sure it doesn't look untaken - profile_taken_branch(target_bci, !ProfileInterpreter); uncommon_trap(Deoptimization::Reason_unreached, Deoptimization::Action_reinterpret, NULL, "cold"); @@ -1485,8 +1462,6 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { branch_block->next_path_num(); } } else { // Path is live. - // Update method data - profile_taken_branch(target_bci); adjust_map_after_if(btest, c, prob, branch_block, next_block); if (!stopped()) { merge(target_bci); @@ -1505,8 +1480,6 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { next_block->next_path_num(); } } else { // Path is live. - // Update method data - profile_not_taken_branch(); adjust_map_after_if(BoolTest(btest).negate(), c, 1.0-prob, next_block, branch_block); } @@ -1528,11 +1501,6 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { tty->print_cr("Never-taken edge stops compilation at bci %d", bci()); } repush_if_args(); // to gather stats on loop - // We need to mark this branch as taken so that if we recompile we will - // see that it is possible. In the tiered system the interpreter doesn't - // do profiling and by the time we get to the lower tier from the interpreter - // the path may be cold again. Make sure it doesn't look untaken - profile_taken_branch(target_bci, !ProfileInterpreter); uncommon_trap(Deoptimization::Reason_unreached, Deoptimization::Action_reinterpret, NULL, "cold"); @@ -1607,8 +1575,6 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { branch_block->next_path_num(); } } else { - // Update method data - profile_taken_branch(target_bci); adjust_map_after_if(taken_btest, c, prob, branch_block, next_block); if (!stopped()) { merge(target_bci); @@ -1626,8 +1592,6 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { next_block->next_path_num(); } } else { - // Update method data - profile_not_taken_branch(); adjust_map_after_if(untaken_btest, c, untaken_prob, next_block, branch_block); } @@ -2691,9 +2655,6 @@ void Parse::do_one_bytecode() { // If this is a backwards branch in the bytecodes, add Safepoint maybe_add_safepoint(target_bci); - // Update method data - profile_taken_branch(target_bci); - // Merge the current control into the target basic block merge(target_bci); diff --git a/src/hotspot/share/opto/parseHelper.cpp b/src/hotspot/share/opto/parseHelper.cpp index d214c2a97b3..c885f7806b1 100644 --- a/src/hotspot/share/opto/parseHelper.cpp +++ b/src/hotspot/share/opto/parseHelper.cpp @@ -86,9 +86,6 @@ void Parse::do_checkcast() { } null_assert(obj); assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" ); - if (!stopped()) { - profile_null_checkcast(); - } return; } @@ -299,287 +296,3 @@ void Parse::dump_map_adr_mem() const { #endif - -//============================================================================= -// -// parser methods for profiling - - -//----------------------test_counter_against_threshold ------------------------ -void Parse::test_counter_against_threshold(Node* cnt, int limit) { - // Test the counter against the limit and uncommon trap if greater. - - // This code is largely copied from the range check code in - // array_addressing() - - // Test invocation count vs threshold - Node *threshold = makecon(TypeInt::make(limit)); - Node *chk = _gvn.transform( new CmpUNode( cnt, threshold) ); - BoolTest::mask btest = BoolTest::lt; - Node *tst = _gvn.transform( new BoolNode( chk, btest) ); - // Branch to failure if threshold exceeded - { BuildCutout unless(this, tst, PROB_ALWAYS); - uncommon_trap(Deoptimization::Reason_age, - Deoptimization::Action_maybe_recompile); - } -} - -//----------------------increment_and_test_invocation_counter------------------- -void Parse::increment_and_test_invocation_counter(int limit) { - if (!count_invocations()) return; - - // Get the Method* node. - ciMethod* m = method(); - MethodCounters* counters_adr = m->ensure_method_counters(); - if (counters_adr == NULL) { - C->record_failure("method counters allocation failed"); - return; - } - - Node* ctrl = control(); - const TypePtr* adr_type = TypeRawPtr::make((address) counters_adr); - Node *counters_node = makecon(adr_type); - Node* adr_iic_node = basic_plus_adr(counters_node, counters_node, - MethodCounters::interpreter_invocation_counter_offset_in_bytes()); - Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - - test_counter_against_threshold(cnt, limit); - - // Add one to the counter and store - Node* incr = _gvn.transform(new AddINode(cnt, _gvn.intcon(1))); - store_to_memory(ctrl, adr_iic_node, incr, T_INT, adr_type, MemNode::unordered); -} - -//----------------------------method_data_addressing--------------------------- -Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { - // Get offset within MethodData* of the data array - ByteSize data_offset = MethodData::data_offset(); - - // Get cell offset of the ProfileData within data array - int cell_offset = md->dp_to_di(data->dp()); - - // Add in counter_offset, the # of bytes into the ProfileData of counter or flag - int offset = in_bytes(data_offset) + cell_offset + in_bytes(counter_offset); - - const TypePtr* adr_type = TypeMetadataPtr::make(md); - Node* mdo = makecon(adr_type); - Node* ptr = basic_plus_adr(mdo, mdo, offset); - - if (stride != 0) { - Node* str = _gvn.MakeConX(stride); - Node* scale = _gvn.transform( new MulXNode( idx, str ) ); - ptr = _gvn.transform( new AddPNode( mdo, ptr, scale ) ); - } - - return ptr; -} - -//--------------------------increment_md_counter_at---------------------------- -void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { - Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride); - - const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - Node* incr = _gvn.transform(new AddINode(cnt, _gvn.intcon(DataLayout::counter_increment))); - store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered); -} - -//--------------------------test_for_osr_md_counter_at------------------------- -void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, int limit) { - Node* adr_node = method_data_addressing(md, data, counter_offset); - - const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - - test_counter_against_threshold(cnt, limit); -} - -//-------------------------------set_md_flag_at-------------------------------- -void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_constant) { - Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset()); - - const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* flags = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - Node* incr = _gvn.transform(new OrINode(flags, _gvn.intcon(flag_constant))); - store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered); -} - -//----------------------------profile_taken_branch----------------------------- -void Parse::profile_taken_branch(int target_bci, bool force_update) { - // This is a potential osr_site if we have a backedge. - int cur_bci = bci(); - bool osr_site = - (target_bci <= cur_bci) && count_invocations() && UseOnStackReplacement; - - // If we are going to OSR, restart at the target bytecode. - set_bci(target_bci); - - // To do: factor out the the limit calculations below. These duplicate - // the similar limit calculations in the interpreter. - - if (method_data_update() || force_update) { - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(cur_bci); - assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch"); - increment_md_counter_at(md, data, JumpData::taken_offset()); - } - - // In the new tiered system this is all we need to do. In the old - // (c2 based) tiered sytem we must do the code below. -#ifndef TIERED - if (method_data_update()) { - ciMethodData* md = method()->method_data(); - if (osr_site) { - ciProfileData* data = md->bci_to_data(cur_bci); - assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch"); - int limit = (int)((int64_t)CompileThreshold - * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); - test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit); - } - } else { - // With method data update off, use the invocation counter to trigger an - // OSR compilation, as done in the interpreter. - if (osr_site) { - int limit = (int)((int64_t)CompileThreshold * OnStackReplacePercentage / 100); - increment_and_test_invocation_counter(limit); - } - } -#endif // TIERED - - // Restore the original bytecode. - set_bci(cur_bci); -} - -//--------------------------profile_not_taken_branch--------------------------- -void Parse::profile_not_taken_branch(bool force_update) { - - if (method_data_update() || force_update) { - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_BranchData(), "need BranchData for not taken branch"); - increment_md_counter_at(md, data, BranchData::not_taken_offset()); - } - -} - -//---------------------------------profile_call-------------------------------- -void Parse::profile_call(Node* receiver) { - if (!method_data_update()) return; - - switch (bc()) { - case Bytecodes::_invokevirtual: - case Bytecodes::_invokeinterface: - profile_receiver_type(receiver); - break; - case Bytecodes::_invokestatic: - case Bytecodes::_invokedynamic: - case Bytecodes::_invokespecial: - profile_generic_call(); - break; - default: fatal("unexpected call bytecode"); - } -} - -//------------------------------profile_generic_call--------------------------- -void Parse::profile_generic_call() { - assert(method_data_update(), "must be generating profile code"); - - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_CounterData(), "need CounterData for not taken branch"); - increment_md_counter_at(md, data, CounterData::count_offset()); -} - -//-----------------------------profile_receiver_type--------------------------- -void Parse::profile_receiver_type(Node* receiver) { - assert(method_data_update(), "must be generating profile code"); - - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_ReceiverTypeData(), "need ReceiverTypeData here"); - - // Skip if we aren't tracking receivers - if (TypeProfileWidth < 1) { - increment_md_counter_at(md, data, CounterData::count_offset()); - return; - } - ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData(); - - Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0)); - - // Using an adr_type of TypePtr::BOTTOM to work around anti-dep problems. - // A better solution might be to use TypeRawPtr::BOTTOM with RC_NARROW_MEM. - make_runtime_call(RC_LEAF, OptoRuntime::profile_receiver_type_Type(), - CAST_FROM_FN_PTR(address, - OptoRuntime::profile_receiver_type_C), - "profile_receiver_type_C", - TypePtr::BOTTOM, - method_data, receiver); -} - -//---------------------------------profile_ret--------------------------------- -void Parse::profile_ret(int target_bci) { - if (!method_data_update()) return; - - // Skip if we aren't tracking ret targets - if (TypeProfileWidth < 1) return; - - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_RetData(), "need RetData for ret"); - ciRetData* ret_data = (ciRetData*)data->as_RetData(); - - // Look for the target_bci is already in the table - uint row; - bool table_full = true; - for (row = 0; row < ret_data->row_limit(); row++) { - int key = ret_data->bci(row); - table_full &= (key != RetData::no_bci); - if (key == target_bci) break; - } - - if (row >= ret_data->row_limit()) { - // The target_bci was not found in the table. - if (!table_full) { - // XXX: Make slow call to update RetData - } - return; - } - - // the target_bci is already in the table - increment_md_counter_at(md, data, RetData::bci_count_offset(row)); -} - -//--------------------------profile_null_checkcast---------------------------- -void Parse::profile_null_checkcast() { - // Set the null-seen flag, done in conjunction with the usual null check. We - // never unset the flag, so this is a one-way switch. - if (!method_data_update()) return; - - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_BitData(), "need BitData for checkcast"); - set_md_flag_at(md, data, BitData::null_seen_byte_constant()); -} - -//-----------------------------profile_switch_case----------------------------- -void Parse::profile_switch_case(int table_index) { - if (!method_data_update()) return; - - ciMethodData* md = method()->method_data(); - assert(md != NULL, "expected valid ciMethodData"); - - ciProfileData* data = md->bci_to_data(bci()); - assert(data != NULL && data->is_MultiBranchData(), "need MultiBranchData for switch case"); - if (table_index >= 0) { - increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index)); - } else { - increment_md_counter_at(md, data, MultiBranchData::default_count_offset()); - } -} diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index fb6ef4a154c..f38a3a205d6 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1210,60 +1210,6 @@ const TypeFunc* OptoRuntime::osr_end_Type() { return TypeFunc::make(domain, range); } -//-------------- methodData update helpers - -const TypeFunc* OptoRuntime::profile_receiver_type_Type() { - // create input type (domain) - const Type **fields = TypeTuple::fields(2); - fields[TypeFunc::Parms+0] = TypeAryPtr::NOTNULL; // methodData pointer - fields[TypeFunc::Parms+1] = TypeInstPtr::BOTTOM; // receiver oop - const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); - - // create result type - fields = TypeTuple::fields(1); - fields[TypeFunc::Parms+0] = NULL; // void - const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); - return TypeFunc::make(domain,range); -} - -JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* receiver)) - if (receiver == NULL) return; - Klass* receiver_klass = receiver->klass(); - - intptr_t* mdp = ((intptr_t*)(data)) + DataLayout::header_size_in_cells(); - int empty_row = -1; // free row, if any is encountered - - // ReceiverTypeData* vc = new ReceiverTypeData(mdp); - for (uint row = 0; row < ReceiverTypeData::row_limit(); row++) { - // if (vc->receiver(row) == receiver_klass) - int receiver_off = ReceiverTypeData::receiver_cell_index(row); - intptr_t row_recv = *(mdp + receiver_off); - if (row_recv == (intptr_t) receiver_klass) { - // vc->set_receiver_count(row, vc->receiver_count(row) + DataLayout::counter_increment); - int count_off = ReceiverTypeData::receiver_count_cell_index(row); - *(mdp + count_off) += DataLayout::counter_increment; - return; - } else if (row_recv == 0) { - // else if (vc->receiver(row) == NULL) - empty_row = (int) row; - } - } - - if (empty_row != -1) { - int receiver_off = ReceiverTypeData::receiver_cell_index(empty_row); - // vc->set_receiver(empty_row, receiver_klass); - *(mdp + receiver_off) = (intptr_t) receiver_klass; - // vc->set_receiver_count(empty_row, DataLayout::counter_increment); - int count_off = ReceiverTypeData::receiver_count_cell_index(empty_row); - *(mdp + count_off) = DataLayout::counter_increment; - } else { - // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polymorphic case. - intptr_t* count_p = (intptr_t*)(((uint8_t*)(data)) + in_bytes(CounterData::count_offset())); - *count_p += DataLayout::counter_increment; - } -JRT_END - //------------------------------------------------------------------------------------- // register policy diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index ffd5280d762..8f07b71de33 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -229,9 +229,6 @@ class OptoRuntime : public AllStatic { static ExceptionBlob* exception_blob() { return _exception_blob; } - // Leaf routines helping with method data update - static void profile_receiver_type_C(DataLayout* data, oopDesc* receiver); - // Implicit exception support static void throw_div0_exception_C (JavaThread* thread); static void throw_stack_overflow_error_C(JavaThread* thread); @@ -304,9 +301,6 @@ class OptoRuntime : public AllStatic { // leaf on stack replacement interpreter accessor types static const TypeFunc* osr_end_Type(); - // leaf methodData routine types - static const TypeFunc* profile_receiver_type_Type(); - // leaf on stack replacement interpreter accessor types static const TypeFunc* fetch_int_Type(); static const TypeFunc* fetch_long_Type(); diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index b5685a36460..a7515d3603e 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -91,6 +91,8 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) : #endif } +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) { assert(UseSuperWord, "should be"); @@ -470,7 +472,7 @@ void SuperWord::SLP_extract() { CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop()); if (cl->is_main_loop()) { - if (_do_vector_loop) { + if (_do_vector_loop_experimental) { if (mark_generations() != -1) { hoist_loads_in_graph(); // this only rebuild the graph; all basic structs need rebuild explicitly @@ -508,11 +510,13 @@ void SuperWord::SLP_extract() { extend_packlist(); - if (_do_vector_loop) { + if (_do_vector_loop_experimental) { if (_packset.length() == 0) { +#ifndef PRODUCT if (TraceSuperWord) { tty->print_cr("\nSuperWord::_do_vector_loop DFA could not build packset, now trying to build anyway"); } +#endif pack_parallel(); } } @@ -1723,7 +1727,14 @@ void SuperWord::construct_my_pack_map() { Node_List* p = _packset.at(i); for (uint j = 0; j < p->size(); j++) { Node* s = p->at(j); - assert(my_pack(s) == NULL, "only in one pack"); +#ifdef ASSERT + if (my_pack(s) != NULL) { + s->dump(1); + tty->print_cr("packs[%d]:", i); + print_pack(p); + assert(false, "only in one pack"); + } +#endif set_my_pack(s, p); } } @@ -1738,7 +1749,7 @@ void SuperWord::filter_packs() { bool impl = implemented(pk); if (!impl) { #ifndef PRODUCT - if (TraceSuperWord && Verbose) { + if ((TraceSuperWord && Verbose) || _vector_loop_debug) { tty->print_cr("Unimplemented"); pk->at(0)->dump(); } @@ -1762,7 +1773,7 @@ void SuperWord::filter_packs() { bool prof = profitable(pk); if (!prof) { #ifndef PRODUCT - if (TraceSuperWord && Verbose) { + if ((TraceSuperWord && Verbose) || _vector_loop_debug) { tty->print_cr("Unprofitable"); pk->at(0)->dump(); } @@ -3052,12 +3063,13 @@ bool SuperWord::construct_bb() { int ii_current = -1; unsigned int load_idx = (unsigned int)-1; - _ii_order.clear(); + // Build iterations order if needed + bool build_ii_order = _do_vector_loop_experimental && _ii_order.is_empty(); // Create real map of block indices for nodes for (int j = 0; j < _block.length(); j++) { Node* n = _block.at(j); set_bb_idx(n, j); - if (_do_vector_loop && n->is_Load()) { + if (build_ii_order && n->is_Load()) { if (ii_current == -1) { ii_current = _clone_map.gen(n->_idx); _ii_order.push(ii_current); @@ -4700,6 +4712,15 @@ bool SuperWord::pack_parallel() { _packset.clear(); + if (_ii_order.is_empty()) { +#ifndef PRODUCT + if (_vector_loop_debug) { + tty->print_cr("SuperWord::pack_parallel: EMPTY"); + } +#endif + return false; + } + for (int ii = 0; ii < _iteration_first.length(); ii++) { Node* nd = _iteration_first.at(ii); if (in_bb(nd) && (nd->is_Load() || nd->is_Store() || nd->is_Add() || nd->is_Mul())) { diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 7cab2f2411f..85dfd406622 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -1653,17 +1653,9 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) { // Eagerly reallocate scalar replaced objects. JavaThread* current_thread = JavaThread::current(); EscapeBarrier eb(true, current_thread, java_thread); - if (eb.barrier_active()) { - if (java_thread->frames_to_pop_failed_realloc() > 0) { - // VM is in the process of popping the top frame because it has scalar replaced objects which - // could not be reallocated on the heap. - // Return JVMTI_ERROR_OUT_OF_MEMORY to avoid interfering with the VM. - return JVMTI_ERROR_OUT_OF_MEMORY; - } - if (!eb.deoptimize_objects(1)) { - // Reallocation of scalar replaced objects failed -> return with error - return JVMTI_ERROR_OUT_OF_MEMORY; - } + if (!eb.deoptimize_objects(1)) { + // Reallocation of scalar replaced objects failed -> return with error + return JVMTI_ERROR_OUT_OF_MEMORY; } MutexLocker mu(JvmtiThreadState_lock); diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index b0d96f94aba..2065aa68f8c 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1378,17 +1378,9 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState // Eagerly reallocate scalar replaced objects. JavaThread* current_thread = JavaThread::current(); EscapeBarrier eb(true, current_thread, java_thread); - if (eb.barrier_active()) { - if (java_thread->frames_to_pop_failed_realloc() > 0) { - // VM is in the process of popping the top frame because it has scalar replaced objects - // which could not be reallocated on the heap. - // Return JVMTI_ERROR_OUT_OF_MEMORY to avoid interfering with the VM. - return JVMTI_ERROR_OUT_OF_MEMORY; - } - if (!eb.deoptimize_objects(0)) { - // Reallocation of scalar replaced objects failed -> return with error - return JVMTI_ERROR_OUT_OF_MEMORY; - } + if (!eb.deoptimize_objects(0)) { + // Reallocation of scalar replaced objects failed -> return with error + return JVMTI_ERROR_OUT_OF_MEMORY; } SetForceEarlyReturn op(state, value, tos); diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index bb8875140ca..1617db70a8d 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -628,58 +628,12 @@ static bool can_be_deoptimized(vframe* vf) { return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized()); } -// Revert optimizations based on escape analysis if this is an access to a local object -bool VM_GetOrSetLocal::deoptimize_objects(javaVFrame* jvf) { -#if COMPILER2_OR_JVMCI - assert(_type == T_OBJECT, "EscapeBarrier should not be active if _type != T_OBJECT"); - if (_depth < _thread->frames_to_pop_failed_realloc()) { - // cannot access frame with failed reallocations +bool VM_GetOrSetLocal::doit_prologue() { + if (!_eb.deoptimize_objects(_depth, _depth)) { + // The target frame is affected by a reallocation failure. _result = JVMTI_ERROR_OUT_OF_MEMORY; return false; } - if (can_be_deoptimized(jvf)) { - compiledVFrame* cf = compiledVFrame::cast(jvf); - if (cf->has_ea_local_in_scope() && !_eb.deoptimize_objects(cf->fr().id())) { - // reallocation of scalar replaced objects failed because heap is exhausted - _result = JVMTI_ERROR_OUT_OF_MEMORY; - return false; - } - } - - // With this access the object could escape the thread changing its escape state from ArgEscape, - // to GlobalEscape so we must deoptimize callers which could have optimized on the escape state. - vframe* vf = jvf; - do { - // move to next physical frame - while(!vf->is_top()) { - vf = vf->sender(); - } - vf = vf->sender(); - - if (vf != NULL && vf->is_compiled_frame()) { - compiledVFrame* cvf = compiledVFrame::cast(vf); - // Deoptimize objects if arg escape is being passed down the stack. - // Note that deoptimizing the frame is not enough because objects need to be relocked - if (cvf->arg_escape() && !_eb.deoptimize_objects(cvf->fr().id())) { - // reallocation of scalar replaced objects failed because heap is exhausted - _result = JVMTI_ERROR_OUT_OF_MEMORY; - return false; - } - } - } while(vf != NULL && !vf->is_entry_frame()); -#endif // COMPILER2_OR_JVMCI - return true; -} - -bool VM_GetOrSetLocal::doit_prologue() { - if (_eb.barrier_active()) { - _jvf = get_java_vframe(); - NULL_CHECK(_jvf, false); - - if (!deoptimize_objects(_jvf)) { - return false; - } - } return true; } diff --git a/src/hotspot/share/prims/jvmtiImpl.hpp b/src/hotspot/share/prims/jvmtiImpl.hpp index 7a3a2197b68..1895f9ab8e6 100644 --- a/src/hotspot/share/prims/jvmtiImpl.hpp +++ b/src/hotspot/share/prims/jvmtiImpl.hpp @@ -334,7 +334,6 @@ class VM_GetOrSetLocal : public VM_Operation { javaVFrame* get_java_vframe(); bool check_slot_type_lvt(javaVFrame* vf); bool check_slot_type_no_lvt(javaVFrame* vf); - bool deoptimize_objects(javaVFrame* vf); public: // Constructor for non-object getter diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 43a505d7676..440ddd0c112 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1659,10 +1659,6 @@ void set_object_alignment() { // Oop encoding heap max OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes; - - if (SurvivorAlignmentInBytes == 0) { - SurvivorAlignmentInBytes = ObjectAlignmentInBytes; - } } size_t Arguments::max_heap_for_compressed_oops() { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 1d9b6880202..6c89b3c773f 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -218,11 +218,6 @@ static bool eliminate_allocations(JavaThread* thread, int exec_mode, CompiledMet Thread* THREAD = thread; // Clear pending OOM if reallocation fails and return true indicating allocation failure realloc_failures = Deoptimization::realloc_objects(thread, &deoptee, &map, objects, CHECK_AND_CLEAR_(true)); - // Make sure the deoptee frame gets processed after a potential safepoint during - // object reallocation. This is necessary because (a) deoptee_thread can be - // different from the current thread and (b) the deoptee frame does not need to be - // the top frame. - StackWatermarkSet::finish_processing(deoptee_thread, NULL /* context */, StackWatermarkKind::gc); deoptimized_objects = true; } else { JRT_BLOCK diff --git a/src/hotspot/share/runtime/escapeBarrier.cpp b/src/hotspot/share/runtime/escapeBarrier.cpp index b6870e2209b..cc101d86b3e 100644 --- a/src/hotspot/share/runtime/escapeBarrier.cpp +++ b/src/hotspot/share/runtime/escapeBarrier.cpp @@ -33,6 +33,7 @@ #include "runtime/handles.hpp" #include "runtime/handshake.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/keepStackGCProcessed.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/registerMap.hpp" #include "runtime/stackValue.hpp" @@ -62,29 +63,37 @@ bool EscapeBarrier::objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) { return result; } -// Object references of frames up to the given depth are about to be -// accessed. Frames with optimizations based on escape state that is potentially -// changed by the accesses need to be deoptimized and the referenced objects -// need to be reallocated and relocked. Up to depth this is done for frames -// with not escaping objects in scope. For deeper frames it is done only if -// they pass not escaping objects as arguments because they potentially escape -// from callee frames within the given depth. -// The search for deeper frames is ended if an entry frame is found because -// arguments to native methods are considered to escape globally. -bool EscapeBarrier::deoptimize_objects(int depth) { - if (barrier_active() && deoptee_thread()->has_last_Java_frame()) { +// Deoptimize objects of frames of the target thread at depth >= d1 and depth <= d2. +// Deoptimize objects of caller frames if they passed references to ArgEscape objects as arguments. +// Return false in the case of a reallocation failure and true otherwise. +bool EscapeBarrier::deoptimize_objects(int d1, int d2) { + if (!barrier_active()) return true; + if (d1 < deoptee_thread()->frames_to_pop_failed_realloc()) { + // The deoptee thread has frames with reallocation failures on top of its stack. + // These frames are about to be removed. We must not interfere with that and signal failure. + return false; + } + if (deoptee_thread()->has_last_Java_frame()) { assert(calling_thread() == Thread::current(), "should be"); + KeepStackGCProcessedMark ksgcpm(deoptee_thread()); ResourceMark rm(calling_thread()); HandleMark hm(calling_thread()); RegisterMap reg_map(deoptee_thread(), false /* update_map */, false /* process_frames */); vframe* vf = deoptee_thread()->last_java_vframe(®_map); int cur_depth = 0; - while (vf != NULL && ((cur_depth <= depth) || !vf->is_entry_frame())) { + + // Skip frames at depth < d1 + while (vf != NULL && cur_depth < d1) { + cur_depth++; + vf = vf->sender(); + } + + while (vf != NULL && ((cur_depth <= d2) || !vf->is_entry_frame())) { if (vf->is_compiled_frame()) { compiledVFrame* cvf = compiledVFrame::cast(vf); // Deoptimize frame and local objects if any exist. // If cvf is deeper than depth, then we deoptimize iff local objects are passed as args. - bool should_deopt = cur_depth <= depth ? cvf->has_ea_local_in_scope() : cvf->arg_escape(); + bool should_deopt = cur_depth <= d2 ? cvf->has_ea_local_in_scope() : cvf->arg_escape(); if (should_deopt && !deoptimize_objects(cvf->fr().id())) { // reallocation of scalar replaced objects failed because heap is exhausted return false; @@ -109,7 +118,13 @@ bool EscapeBarrier::deoptimize_objects_all_threads() { if (!barrier_active()) return true; ResourceMark rm(calling_thread()); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { + if (jt->frames_to_pop_failed_realloc() > 0) { + // The deoptee thread jt has frames with reallocation failures on top of its stack. + // These frames are about to be removed. We must not interfere with that and signal failure. + return false; + } if (jt->has_last_Java_frame()) { + KeepStackGCProcessedMark ksgcpm(jt); RegisterMap reg_map(jt, false /* update_map */, false /* process_frames */); vframe* vf = jt->last_java_vframe(®_map); assert(jt->frame_anchor()->walkable(), @@ -297,7 +312,7 @@ static void set_objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) { // frame is replaced with interpreter frames. Returns false iff at least one // reallocation failed. bool EscapeBarrier::deoptimize_objects_internal(JavaThread* deoptee, intptr_t* fr_id) { - if (!barrier_active()) return true; + assert(barrier_active(), "should not call"); JavaThread* ct = calling_thread(); bool realloc_failures = false; @@ -307,11 +322,7 @@ bool EscapeBarrier::deoptimize_objects_internal(JavaThread* deoptee, intptr_t* f compiledVFrame* last_cvf; bool fr_is_deoptimized; do { - if (!self_deopt()) { - // Process stack of deoptee thread as we will access oops during object deoptimization. - StackWatermarkSet::start_processing(deoptee, StackWatermarkKind::gc); - } - StackFrameStream fst(deoptee, true /* update */, true /* process_frames */); + StackFrameStream fst(deoptee, true /* update */, false /* process_frames */); while (fst.current()->id() != fr_id && !fst.is_done()) { fst.next(); } diff --git a/src/hotspot/share/runtime/escapeBarrier.hpp b/src/hotspot/share/runtime/escapeBarrier.hpp index 57230cbdb25..96df2827783 100644 --- a/src/hotspot/share/runtime/escapeBarrier.hpp +++ b/src/hotspot/share/runtime/escapeBarrier.hpp @@ -61,6 +61,12 @@ class EscapeBarrier : StackObj { // Deoptimize the given frame and deoptimize objects with optimizations based on escape analysis. bool deoptimize_objects_internal(JavaThread* deoptee, intptr_t* fr_id); + // Deoptimize objects, i.e. reallocate and relock them. The target frames are deoptimized. + // The methods return false iff at least one reallocation failed. + bool deoptimize_objects(intptr_t* fr_id) { + return deoptimize_objects_internal(deoptee_thread(), fr_id); + } + public: // Revert ea based optimizations for given deoptee thread EscapeBarrier(bool barrier_active, JavaThread* calling_thread, JavaThread* deoptee_thread) @@ -89,13 +95,17 @@ class EscapeBarrier : StackObj { bool barrier_active() const { return false; } #endif // COMPILER2_OR_JVMCI - // Deoptimize objects, i.e. reallocate and relock them. The target frames are deoptimized. - // The methods return false iff at least one reallocation failed. - bool deoptimize_objects(intptr_t* fr_id) { - return true COMPILER2_OR_JVMCI_PRESENT(&& deoptimize_objects_internal(deoptee_thread(), fr_id)); + // Deoptimize objects of frames of the target thread up to the given depth. + // Deoptimize objects of caller frames if they passed references to ArgEscape objects as arguments. + // Return false in the case of a reallocation failure and true otherwise. + bool deoptimize_objects(int depth) { + return deoptimize_objects(0, depth); } - bool deoptimize_objects(int depth) NOT_COMPILER2_OR_JVMCI_RETURN_(true); + // Deoptimize objects of frames of the target thread at depth >= d1 and depth <= d2. + // Deoptimize objects of caller frames if they passed references to ArgEscape objects as arguments. + // Return false in the case of a reallocation failure and true otherwise. + bool deoptimize_objects(int d1, int d2) NOT_COMPILER2_OR_JVMCI_RETURN_(true); // Find and deoptimize non escaping objects and the holding frames on all stacks. bool deoptimize_objects_all_threads() NOT_COMPILER2_OR_JVMCI_RETURN_(true); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 4b77de98941..6ae94f95a5c 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2393,11 +2393,6 @@ const intx ObjectAlignmentInBytes = 8; product(bool, WhiteBoxAPI, false, DIAGNOSTIC, \ "Enable internal testing APIs") \ \ - product(intx, SurvivorAlignmentInBytes, 0, EXPERIMENTAL, \ - "Default survivor space alignment in bytes") \ - range(8, 256) \ - constraint(SurvivorAlignmentInBytesConstraintFunc,AfterErgo) \ - \ product(ccstr, DumpLoadedClassList, NULL, \ "Dump the names all loaded classes, that could be stored into " \ "the CDS archive, in the specified file") \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index be27009fb83..3e0a274a247 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -688,6 +688,7 @@ void vm_shutdown_during_initialization(const char* error, const char* message) { } JDK_Version JDK_Version::_current; +const char* JDK_Version::_java_version; const char* JDK_Version::_runtime_name; const char* JDK_Version::_runtime_version; const char* JDK_Version::_runtime_vendor_version; diff --git a/src/hotspot/share/runtime/java.hpp b/src/hotspot/share/runtime/java.hpp index 66a93c4f4cc..c24b2619c6e 100644 --- a/src/hotspot/share/runtime/java.hpp +++ b/src/hotspot/share/runtime/java.hpp @@ -65,6 +65,7 @@ class JDK_Version { private: static JDK_Version _current; + static const char* _java_version; static const char* _runtime_name; static const char* _runtime_version; static const char* _runtime_vendor_version; @@ -130,6 +131,13 @@ class JDK_Version { void to_string(char* buffer, size_t buflen) const; + static const char* java_version() { + return _java_version; + } + static void set_java_version(const char* version) { + _java_version = version; + } + static const char* runtime_name() { return _runtime_name; } diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.cpp b/src/hotspot/share/runtime/keepStackGCProcessed.cpp new file mode 100644 index 00000000000..df851b9f1cc --- /dev/null +++ b/src/hotspot/share/runtime/keepStackGCProcessed.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/stackWatermark.inline.hpp" +#include "runtime/stackWatermarkSet.inline.hpp" +#include "runtime/keepStackGCProcessed.hpp" + +KeepStackGCProcessedMark::KeepStackGCProcessedMark(JavaThread* jt) : + _active(true), + _jt(jt) { + finish_processing(); + if (!Thread::current()->is_Java_thread()) { + assert(SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread(), + "must be either Java thread or VM thread in a safepoint"); + _active = false; + return; + } + StackWatermark* our_watermark = StackWatermarkSet::get(JavaThread::current(), StackWatermarkKind::gc); + if (our_watermark == NULL) { + _active = false; + return; + } + StackWatermark* their_watermark = StackWatermarkSet::get(jt, StackWatermarkKind::gc); + our_watermark->link_watermark(their_watermark); +} + +KeepStackGCProcessedMark::~KeepStackGCProcessedMark() { + if (!_active) { + return; + } + StackWatermark* our_watermark = StackWatermarkSet::get(JavaThread::current(), StackWatermarkKind::gc); + our_watermark->link_watermark(NULL); +} + +void KeepStackGCProcessedMark::finish_processing() { + StackWatermarkSet::finish_processing(_jt, NULL /* context */, StackWatermarkKind::gc); +} diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.hpp b/src/hotspot/share/runtime/keepStackGCProcessed.hpp new file mode 100644 index 00000000000..2c36991fe28 --- /dev/null +++ b/src/hotspot/share/runtime/keepStackGCProcessed.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_RUNTIME_KEEPSTACKGCPROCESSED_HPP +#define SHARE_RUNTIME_KEEPSTACKGCPROCESSED_HPP + +#include "memory/allocation.hpp" +#include "runtime/stackWatermark.hpp" +#include "runtime/stackWatermarkKind.hpp" +#include "runtime/stackWatermarkSet.hpp" + +// Use this class to mark a remote thread you are currently interested +// in examining the entire stack, without it slipping into an unprocessed +// state at safepoint polls. +class KeepStackGCProcessedMark : public StackObj { + friend class StackWatermark; + bool _active; + JavaThread* _jt; + + void finish_processing(); + +public: + KeepStackGCProcessedMark(JavaThread* jt); + ~KeepStackGCProcessedMark(); +}; + + +#endif // SHARE_RUNTIME_KEEPSTACKGCPROCESSED_HPP diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 9a7e50f2946..433818c8d24 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1658,38 +1658,10 @@ char* os::reserve_memory(size_t bytes, MEMFLAGS flags) { return result; } -char* os::reserve_memory_with_fd(size_t bytes, int file_desc) { - char* result; - - if (file_desc != -1) { - // Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(), - // but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file. - result = os::map_memory_to_file(NULL /* addr */, bytes, file_desc); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve_and_commit(result, bytes, CALLER_PC); - } - } else { - result = pd_reserve_memory(bytes); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC); - } - } - - return result; -} - -char* os::attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc) { - char* result = NULL; - if (file_desc != -1) { - result = pd_attempt_reserve_memory_at(addr, bytes, file_desc); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); - } - } else { - result = pd_attempt_reserve_memory_at(addr, bytes); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); - } +char* os::attempt_reserve_memory_at(char* addr, size_t bytes) { + char* result = pd_attempt_reserve_memory_at(addr, bytes); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } return result; } @@ -1758,6 +1730,25 @@ void os::pretouch_memory(void* start, void* end, size_t page_size) { } } +char* os::map_memory_to_file(size_t bytes, int file_desc) { + // Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(), + // but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file. + // On all current implementations NULL is interpreted as any available address. + char* result = os::map_memory_to_file(NULL /* addr */, bytes, file_desc); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve_and_commit(result, bytes, CALLER_PC); + } + return result; +} + +char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc) { + char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); + } + return result; +} + char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, bool allow_exec, MEMFLAGS flags) { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index eb51d771105..d91b9f561ca 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -116,7 +116,6 @@ class os: AllStatic { static char* pd_reserve_memory(size_t bytes); static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes); - static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc); static bool pd_commit_memory(char* addr, size_t bytes, bool executable); static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint, @@ -131,6 +130,8 @@ class os: AllStatic { static bool pd_uncommit_memory(char* addr, size_t bytes); static bool pd_release_memory(char* addr, size_t bytes); + static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc); + static char* pd_map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only = false, bool allow_exec = false); @@ -313,19 +314,14 @@ class os: AllStatic { static int vm_allocation_granularity(); // Reserves virtual memory. - // alignment_hint - currently only used by AIX static char* reserve_memory(size_t bytes, MEMFLAGS flags = mtOther); - // Reserves virtual memory. - // if file_desc != -1, also attaches the memory to the file. - static char* reserve_memory_with_fd(size_t bytes, int file_desc); - // Reserves virtual memory that starts at an address that is aligned to 'alignment'. - static char* reserve_memory_aligned(size_t size, size_t alignment, int file_desc = -1); + static char* reserve_memory_aligned(size_t size, size_t alignment); // Attempts to reserve the virtual memory at [addr, addr + bytes). // Does not overwrite existing mappings. - static char* attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc = -1); + static char* attempt_reserve_memory_at(char* addr, size_t bytes); // Split a reserved memory region [base, base+size) into two regions [base, base+split) and // [base+split, base+size). @@ -370,7 +366,10 @@ class os: AllStatic { static int create_file_for_heap(const char* dir); // Map memory to the file referred by fd. This function is slightly different from map_memory() // and is added to be used for implementation of -XX:AllocateHeapAt + static char* map_memory_to_file(size_t size, int fd); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd); static char* map_memory_to_file(char* base, size_t size, int fd); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd); // Replace existing reserved memory with file mapping static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index 2218b527d16..bb10694b000 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -83,13 +83,13 @@ void SafepointMechanism::process(JavaThread *thread) { SafepointSynchronize::block(thread); // Recursive } - // The call to start_processing fixes the thread's oops and the first few frames. + // The call to on_safepoint fixes the thread's oops and the first few frames. // // The call has been carefully placed here to cater for a few situations: // 1) After we exit from block after a global poll // 2) After a thread races with the disarming of the global poll and transitions from native/blocked // 3) Before the handshake code is run - StackWatermarkSet::start_processing(thread, StackWatermarkKind::gc); + StackWatermarkSet::on_safepoint(thread); if (thread->handshake_state()->should_process()) { thread->handshake_state()->process_by_self(); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index ccedbdaddb4..95369e6272e 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -2454,15 +2454,12 @@ class AdapterHandlerTable : public BasicHashtable { public: AdapterHandlerTable() - : BasicHashtable(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { } + : BasicHashtable(293, (sizeof(AdapterHandlerEntry))) { } // Create a new entry suitable for insertion in the table AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) { AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); - if (DumpSharedSpaces) { - ((CDSAdapterHandlerEntry*)entry)->init(); - } return entry; } @@ -3130,17 +3127,6 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const { st->cr(); } -#if INCLUDE_CDS - -void CDSAdapterHandlerEntry::init() { - assert(DumpSharedSpaces, "used during dump time only"); - _c2i_entry_trampoline = (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size()); - _adapter_trampoline = (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*)); -}; - -#endif // INCLUDE_CDS - - #ifndef PRODUCT void AdapterHandlerLibrary::print_statistics() { diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 32b9786f0cb..1dc5294c1d9 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -679,20 +679,6 @@ class AdapterHandlerEntry : public BasicHashtableEntry { void print_adapter_on(outputStream* st) const; }; -// This class is used only with DumpSharedSpaces==true. It holds extra information -// that's used only during CDS dump time. -// For details, see comments around Method::link_method() -class CDSAdapterHandlerEntry: public AdapterHandlerEntry { - address _c2i_entry_trampoline; // allocated from shared spaces "MC" region - AdapterHandlerEntry** _adapter_trampoline; // allocated from shared spaces "MD" region - -public: - address get_c2i_entry_trampoline() const { return _c2i_entry_trampoline; } - AdapterHandlerEntry** get_adapter_trampoline() const { return _adapter_trampoline; } - void init() NOT_CDS_RETURN; -}; - - class AdapterHandlerLibrary: public AllStatic { private: static BufferBlob* _buffer; // the temporary code buffer in CodeCache diff --git a/src/hotspot/share/runtime/stackOverflow.hpp b/src/hotspot/share/runtime/stackOverflow.hpp index 45a2314f022..c8e4249ab25 100644 --- a/src/hotspot/share/runtime/stackOverflow.hpp +++ b/src/hotspot/share/runtime/stackOverflow.hpp @@ -137,12 +137,15 @@ class StackOverflow { return _stack_red_zone_size; } + // Returns base of red zone (one-beyond the highest red zone address, so + // itself outside red zone and the highest address of the yellow zone). address stack_red_zone_base() const { return (address)(stack_end() + stack_red_zone_size()); } + // Returns true if address points into the red zone. bool in_stack_red_zone(address a) const { - return a <= stack_red_zone_base() && a >= stack_end(); + return a < stack_red_zone_base() && a >= stack_end(); } static size_t stack_yellow_zone_size() { @@ -155,20 +158,25 @@ class StackOverflow { return _stack_reserved_zone_size; } + // Returns base of the reserved zone (one-beyond the highest reserved zone address). address stack_reserved_zone_base() const { return (address)(stack_end() + (stack_red_zone_size() + stack_yellow_zone_size() + stack_reserved_zone_size())); } + + // Returns true if address points into the reserved zone. bool in_stack_reserved_zone(address a) const { - return (a <= stack_reserved_zone_base()) && + return (a < stack_reserved_zone_base()) && (a >= (address)((intptr_t)stack_reserved_zone_base() - stack_reserved_zone_size())); } static size_t stack_yellow_reserved_zone_size() { return _stack_yellow_zone_size + _stack_reserved_zone_size; } + + // Returns true if a points into either yellow or reserved zone. bool in_stack_yellow_reserved_zone(address a) const { - return (a <= stack_reserved_zone_base()) && (a >= stack_red_zone_base()); + return (a < stack_reserved_zone_base()) && (a >= stack_red_zone_base()); } // Size of red + yellow + reserved zones. diff --git a/src/hotspot/share/runtime/stackWatermark.cpp b/src/hotspot/share/runtime/stackWatermark.cpp index 1dbd3f8c860..2d6722f2e8c 100644 --- a/src/hotspot/share/runtime/stackWatermark.cpp +++ b/src/hotspot/share/runtime/stackWatermark.cpp @@ -163,7 +163,8 @@ StackWatermark::StackWatermark(JavaThread* jt, StackWatermarkKind kind, uint32_t _jt(jt), _iterator(NULL), _lock(Mutex::tty - 1, "stack_watermark_lock", true, Mutex::_safepoint_check_never), - _kind(kind) { + _kind(kind), + _linked_watermark(NULL) { } StackWatermark::~StackWatermark() { @@ -247,6 +248,11 @@ void StackWatermark::process_one() { } } +void StackWatermark::link_watermark(StackWatermark* watermark) { + assert(watermark == NULL || _linked_watermark == NULL, "nesting not supported"); + _linked_watermark = watermark; +} + uintptr_t StackWatermark::watermark() { return Atomic::load_acquire(&_watermark); } @@ -280,6 +286,14 @@ bool StackWatermark::processing_completed_acquire() const { return processing_completed(Atomic::load_acquire(&_state)); } +void StackWatermark::on_safepoint() { + start_processing(); + StackWatermark* linked_watermark = _linked_watermark; + if (linked_watermark != NULL) { + linked_watermark->finish_processing(NULL /* context */); + } +} + void StackWatermark::start_processing() { if (!processing_started_acquire()) { MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index df0c13840b9..342bbd15613 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -26,6 +26,7 @@ #define SHARE_RUNTIME_STACKWATERMARK_HPP #include "memory/allocation.hpp" +#include "runtime/mutex.hpp" #include "runtime/stackWatermarkKind.hpp" class frame; @@ -92,6 +93,7 @@ class StackWatermark : public CHeapObj { StackWatermarkFramesIterator* _iterator; Mutex _lock; StackWatermarkKind _kind; + StackWatermark* _linked_watermark; void process_one(); @@ -127,6 +129,8 @@ class StackWatermark : public CHeapObj { StackWatermark* next() const { return _next; } void set_next(StackWatermark* n) { _next = n; } + void link_watermark(StackWatermark* watermark); + uintptr_t watermark(); uintptr_t last_processed(); @@ -139,6 +143,7 @@ class StackWatermark : public CHeapObj { void after_unwind(); void on_iteration(const frame& f); + void on_safepoint(); void start_processing(); void finish_processing(void* context); }; diff --git a/src/hotspot/share/runtime/stackWatermark.inline.hpp b/src/hotspot/share/runtime/stackWatermark.inline.hpp index 161c7687e83..93c92234457 100644 --- a/src/hotspot/share/runtime/stackWatermark.inline.hpp +++ b/src/hotspot/share/runtime/stackWatermark.inline.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_RUNTIME_STACKWATERMARK_INLINE_HPP #define SHARE_RUNTIME_STACKWATERMARK_INLINE_HPP +#include "code/nmethod.hpp" #include "runtime/stackWatermark.hpp" #include "runtime/thread.hpp" diff --git a/src/hotspot/share/runtime/stackWatermarkSet.cpp b/src/hotspot/share/runtime/stackWatermarkSet.cpp index 617e3b38448..e2836797120 100644 --- a/src/hotspot/share/runtime/stackWatermarkSet.cpp +++ b/src/hotspot/share/runtime/stackWatermarkSet.cpp @@ -109,6 +109,13 @@ void StackWatermarkSet::on_iteration(JavaThread* jt, const frame& fr) { // calling this might not be Thread::current(). } +void StackWatermarkSet::on_safepoint(JavaThread* jt) { + StackWatermark* watermark = get(jt, StackWatermarkKind::gc); + if (watermark != NULL) { + watermark->on_safepoint(); + } +} + void StackWatermarkSet::start_processing(JavaThread* jt, StackWatermarkKind kind) { verify_processing_context(); assert(!jt->is_terminated(), "Poll after termination is a bug"); diff --git a/src/hotspot/share/runtime/stackWatermarkSet.hpp b/src/hotspot/share/runtime/stackWatermarkSet.hpp index ee3af3ceff4..78cfc7f2827 100644 --- a/src/hotspot/share/runtime/stackWatermarkSet.hpp +++ b/src/hotspot/share/runtime/stackWatermarkSet.hpp @@ -73,6 +73,9 @@ class StackWatermarkSet : public AllStatic { // Called by stack walkers when walking into a frame static void on_iteration(JavaThread* jt, const frame& fr); + // Called to ensure that processing of the thread is started when waking up from safepoint + static void on_safepoint(JavaThread* jt); + // Called to ensure that processing of the thread is started static void start_processing(JavaThread* jt, StackWatermarkKind kind); diff --git a/src/hotspot/share/runtime/statSampler.cpp b/src/hotspot/share/runtime/statSampler.cpp index 65229be6d30..471e9577a0f 100644 --- a/src/hotspot/share/runtime/statSampler.cpp +++ b/src/hotspot/share/runtime/statSampler.cpp @@ -173,15 +173,15 @@ void StatSampler::collect_sample() { } /* - * method to upcall into Java to return the value of the specified - * property as a utf8 string, or NULL if does not exist. The caller - * is responsible for setting a ResourceMark for proper cleanup of - * the utf8 strings. + * Call into java.lang.System.getProperty to check that the value of the + * specified property matches */ -const char* StatSampler::get_system_property(const char* name, TRAPS) { +void StatSampler::assert_system_property(const char* name, const char* value, TRAPS) { +#ifdef ASSERT + ResourceMark rm(THREAD); // setup the arguments to getProperty - Handle key_str = java_lang_String::create_from_str(name, CHECK_NULL); + Handle key_str = java_lang_String::create_from_str(name, CHECK); // return value JavaValue result(T_OBJECT); @@ -192,100 +192,73 @@ const char* StatSampler::get_system_property(const char* name, TRAPS) { vmSymbols::getProperty_name(), vmSymbols::string_string_signature(), key_str, - CHECK_NULL); + CHECK); oop value_oop = (oop)result.get_jobject(); - if (value_oop == NULL) { - return NULL; - } + assert(value_oop != NULL, "property must have a value"); // convert Java String to utf8 string - char* value = java_lang_String::as_utf8_string(value_oop); + char* system_value = java_lang_String::as_utf8_string(value_oop); - return value; + assert(strcmp(value, system_value) == 0, "property value mustn't differ from System.getProperty"); +#endif // ASSERT } /* - * The list of System Properties that have corresponding PerfData - * string instrumentation created by retrieving the named property's - * value from System.getProperty() and unconditionally creating a - * PerfStringConstant object initialized to the retrieved value. This - * is not an exhaustive list of Java properties with corresponding string - * instrumentation as the create_system_property_instrumentation() method - * creates other property based instrumentation conditionally. + * Adds a constant counter of the given property. Asserts the value does not + * differ from the value retrievable from System.getProperty(name) */ +void StatSampler::add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS) { + // the property must exist + assert(value != NULL, "property name should be have a value: %s", name); + assert_system_property(name, value, CHECK); + if (value != NULL) { + // create the property counter + PerfDataManager::create_string_constant(name_space, name, value, CHECK); + } +} -// stable interface, supported counters -static const char* property_counters_ss[] = { - "java.vm.specification.version", - "java.vm.specification.name", - "java.vm.specification.vendor", - "java.vm.version", - "java.vm.name", - "java.vm.vendor", - "java.vm.info", - "jdk.debug", - "java.library.path", - "java.class.path", - "java.version", - "java.home", - NULL -}; - -// unstable interface, supported counters -static const char* property_counters_us[] = { - NULL -}; - -// unstable interface, unsupported counters -static const char* property_counters_uu[] = { - "sun.boot.library.path", - NULL -}; - -typedef struct { - const char** property_list; - CounterNS name_space; -} PropertyCounters; - -static PropertyCounters property_counters[] = { - { property_counters_ss, JAVA_PROPERTY }, - { property_counters_us, COM_PROPERTY }, - { property_counters_uu, SUN_PROPERTY }, - { NULL, SUN_PROPERTY } -}; - +/* + * Adds a string constant of the given property. Retrieves the value via + * Arguments::get_property() and asserts the value for the does not differ from + * the value retrievable from System.getProperty() + */ +void StatSampler::add_property_constant(CounterNS name_space, const char* name, TRAPS) { + add_property_constant(name_space, name, Arguments::get_property(name), CHECK); +} /* - * Method to create PerfData string instruments that contain the values - * of various system properties. String instruments are created for each - * property specified in the property lists provided in property_counters[]. + * Method to create PerfStringConstants containing the values of various + * system properties. Constants are created from information known to HotSpot, + * but are initialized as-if getting the values from System.getProperty() + * during bootstrap. + * * Property counters have a counter name space prefix prepended to the - * property name as indicated in property_counters[]. + * property name. */ void StatSampler::create_system_property_instrumentation(TRAPS) { - ResourceMark rm; - - for (int i = 0; property_counters[i].property_list != NULL; i++) { - - for (int j = 0; property_counters[i].property_list[j] != NULL; j++) { - - const char* property_name = property_counters[i].property_list[j]; - assert(property_name != NULL, "property name should not be NULL"); - - const char* value = get_system_property(property_name, CHECK); - - // the property must exist - assert(value != NULL, "property name should be valid"); - - if (value != NULL) { - // create the property counter - PerfDataManager::create_string_constant(property_counters[i].name_space, - property_name, value, CHECK); - } - } - } + // Non-writeable, constant properties + add_property_constant(JAVA_PROPERTY, "java.vm.specification.name", "Java Virtual Machine Specification", CHECK); + add_property_constant(JAVA_PROPERTY, "java.version", JDK_Version::java_version(), CHECK); + add_property_constant(JAVA_PROPERTY, "java.vm.version", VM_Version::vm_release(), CHECK); + add_property_constant(JAVA_PROPERTY, "java.vm.name", VM_Version::vm_name(), CHECK); + add_property_constant(JAVA_PROPERTY, "java.vm.vendor", VM_Version::vm_vendor(), CHECK); + add_property_constant(JAVA_PROPERTY, "jdk.debug", VM_Version::jdk_debug_level(), CHECK); + + // Get remaining property constants via Arguments::get_property, + // which does a linear search over the internal system properties list. + + // SUN_PROPERTY properties + add_property_constant(SUN_PROPERTY, "sun.boot.library.path", CHECK); + + // JAVA_PROPERTY properties + add_property_constant(JAVA_PROPERTY, "java.vm.specification.version", CHECK); + add_property_constant(JAVA_PROPERTY, "java.vm.specification.vendor", CHECK); + add_property_constant(JAVA_PROPERTY, "java.vm.info", CHECK); + add_property_constant(JAVA_PROPERTY, "java.library.path", CHECK); + add_property_constant(JAVA_PROPERTY, "java.class.path", CHECK); + add_property_constant(JAVA_PROPERTY, "java.home", CHECK); } /* diff --git a/src/hotspot/share/runtime/statSampler.hpp b/src/hotspot/share/runtime/statSampler.hpp index fb620fbc75c..4590f85302c 100644 --- a/src/hotspot/share/runtime/statSampler.hpp +++ b/src/hotspot/share/runtime/statSampler.hpp @@ -51,7 +51,9 @@ class StatSampler : AllStatic { static void create_misc_perfdata(); static void create_sampled_perfdata(); static void sample_data(PerfDataList* list); - static const char* get_system_property(const char* name, TRAPS); + static void assert_system_property(const char* name, const char* value, TRAPS); + static void add_property_constant(CounterNS name_space, const char* name, TRAPS); + static void add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS); static void create_system_property_instrumentation(TRAPS); public: diff --git a/src/hotspot/share/runtime/stubCodeGenerator.cpp b/src/hotspot/share/runtime/stubCodeGenerator.cpp index 7cbe46781ce..73b8f7b3279 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.cpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.cpp @@ -73,13 +73,13 @@ StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) { } StubCodeGenerator::~StubCodeGenerator() { - if (PRODUCT_ONLY(_print_code) NOT_PRODUCT(true)) { - CodeBuffer* cbuf = _masm->code(); - CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); - if (blob != NULL) { - blob->set_strings(cbuf->strings()); - } +#ifndef PRODUCT + CodeBuffer* cbuf = _masm->code(); + CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); + if (blob != NULL) { + blob->set_strings(cbuf->strings()); } +#endif } void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) { @@ -88,21 +88,16 @@ void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) { void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) { if (_print_code) { - CodeStrings cs; - ptrdiff_t offset = 0; #ifndef PRODUCT // Find the code strings in the outer CodeBuffer. CodeBuffer *outer_cbuf = _masm->code_section()->outer(); - cs = outer_cbuf->strings(); - // The offset from the start of the outer CodeBuffer to the start - // of this stub. - offset = cdesc->begin() - outer_cbuf->insts()->start(); + CodeStrings* cs = &outer_cbuf->strings(); #endif ttyLocker ttyl; tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); cdesc->print_on(tty); tty->cr(); - Disassembler::decode(cdesc->begin(), cdesc->end(), tty, cs /*, offset */); + Disassembler::decode(cdesc->begin(), cdesc->end(), tty NOT_PRODUCT(COMMA cs)); tty->print_cr("- - - [END] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); tty->cr(); } diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 980be2c79c9..7bc6272d3d3 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -894,11 +894,34 @@ static void create_initial_thread(Handle thread_group, JavaThread* thread, java_lang_Thread::RUNNABLE); } +char java_version[64] = ""; char java_runtime_name[128] = ""; char java_runtime_version[128] = ""; char java_runtime_vendor_version[128] = ""; char java_runtime_vendor_vm_bug_url[128] = ""; +// extract the JRE version string from java.lang.VersionProps.java_version +static const char* get_java_version(TRAPS) { + Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), + Handle(), Handle(), CHECK_AND_CLEAR_NULL); + fieldDescriptor fd; + bool found = k != NULL && + InstanceKlass::cast(k)->find_local_field(vmSymbols::java_version_name(), + vmSymbols::string_signature(), &fd); + if (found) { + oop name_oop = k->java_mirror()->obj_field(fd.offset()); + if (name_oop == NULL) { + return NULL; + } + const char* name = java_lang_String::as_utf8_string(name_oop, + java_version, + sizeof(java_version)); + return name; + } else { + return NULL; + } +} + // extract the JRE name from java.lang.VersionProps.java_runtime_name static const char* get_java_runtime_name(TRAPS) { Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), @@ -3383,6 +3406,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { call_initPhase1(CHECK); // get the Java runtime name, version, and vendor info after java.lang.System is initialized + JDK_Version::set_java_version(get_java_version(THREAD)); JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); JDK_Version::set_runtime_vendor_version(get_java_runtime_vendor_version(THREAD)); diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index bec1661d4ce..154672ece92 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -191,13 +191,6 @@ class ConcurrentHashTable : public CHeapObj { Bucket* get_bucket(size_t idx) { return &_buckets[idx]; } }; - // Used as default functor when no functor supplied for some methods. - struct NoOp { - void operator()(VALUE*) {} - const VALUE& operator()() {} - void operator()(bool, VALUE*) {} - } noOp; - // For materializing a supplied value. class LazyValueRetrieve { private: @@ -429,7 +422,10 @@ class ConcurrentHashTable : public CHeapObj { // Same without DELETE_FUNC. template bool remove(Thread* thread, LOOKUP_FUNC& lookup_f) { - return internal_remove(thread, lookup_f, noOp); + struct { + void operator()(VALUE*) {} + } ignore_del_f; + return internal_remove(thread, lookup_f, ignore_del_f); } // Visit all items with SCAN_FUNC if no concurrent resize. Takes the resize diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 8679847f907..28624054212 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -2338,13 +2338,6 @@ public Field[] getDeclaredFields() throws SecurityException { } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns an array of {@code RecordComponent} objects representing all the * record components of this record class, or {@code null} if this class is * not a record class. @@ -2381,11 +2374,8 @@ public Field[] getDeclaredFields() throws SecurityException { * * * @jls 8.10 Record Types - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") @CallerSensitive public RecordComponent[] getRecordComponents() { SecurityManager sm = System.getSecurityManager(); @@ -3682,13 +3672,6 @@ private static Class javaLangRecordClass() { } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns {@code true} if and only if this class is a record class. * *

The {@linkplain #getSuperclass() direct superclass} of a record @@ -3701,10 +3684,8 @@ private static Class javaLangRecordClass() { * * @return true if and only if this class is a record class, otherwise false * @jls 8.10 Record Types - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) public boolean isRecord() { return getSuperclass() == JAVA_LANG_RECORD_CLASS && isRecord0(); } diff --git a/src/java.base/share/classes/java/lang/Record.java b/src/java.base/share/classes/java/lang/Record.java index 4d568e8baa0..121fc7ce73c 100644 --- a/src/java.base/share/classes/java/lang/Record.java +++ b/src/java.base/share/classes/java/lang/Record.java @@ -25,14 +25,6 @@ package java.lang; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Programs can only use this - * class when preview features are enabled. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * This is the common base class of all Java language record classes. * *

More information about records, including descriptions of the @@ -86,10 +78,8 @@ * record serialization. * * @jls 8.10 Record Types - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=true) public abstract class Record { /** * Constructor for record classes to call. diff --git a/src/java.base/share/classes/java/lang/VersionProps.java.template b/src/java.base/share/classes/java/lang/VersionProps.java.template index 4f29c2d5fc3..6037c61b3be 100644 --- a/src/java.base/share/classes/java/lang/VersionProps.java.template +++ b/src/java.base/share/classes/java/lang/VersionProps.java.template @@ -36,6 +36,7 @@ class VersionProps { private static final String launcher_name = "@@LAUNCHER_NAME@@"; + // This field is read by HotSpot private static final String java_version = "@@VERSION_SHORT@@"; 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 15182f2a87b..db4e65a2b45 100644 --- a/src/java.base/share/classes/java/lang/annotation/ElementType.java +++ b/src/java.base/share/classes/java/lang/annotation/ElementType.java @@ -118,22 +118,12 @@ public enum ElementType { MODULE, /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This constant is associated with records, a preview - * feature of the Java language. Programs can only use this - * constant when preview features are enabled. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Record component * * @jls 8.10.3 Record Members * @jls 9.7.4 Where Annotations May Appear * - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=true) RECORD_COMPONENT; } diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 2bf096a3b06..5454eeca025 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -28,6 +28,7 @@ import jdk.internal.misc.CDS; import jdk.internal.org.objectweb.asm.*; import sun.invoke.util.BytecodeDescriptor; +import sun.invoke.util.VerifyAccess; import sun.security.action.GetPropertyAction; import sun.security.action.GetBooleanAction; @@ -66,7 +67,6 @@ private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V"; private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V"; - private static final String DESCR_SET_IMPL_METHOD = "(Ljava/lang/invoke/MethodHandle;)V"; private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; private static final String NAME_METHOD_READ_OBJECT = "readObject"; @@ -87,7 +87,7 @@ private static final String[] EMPTY_STRING_ARRAY = new String[0]; // Used to ensure that each spun class name is unique - private static final AtomicInteger counter = new AtomicInteger(0); + private static final AtomicInteger counter = new AtomicInteger(); // For dumping generated classes to disk, for debugging purposes private static final ProxyClassesDumper dumper; @@ -169,8 +169,8 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); constructorType = invokedType.changeReturnType(Void.TYPE); lambdaClassName = lambdaClassName(targetClass); - useImplMethodHandle = !implClass.getPackageName().equals(implInfo.getDeclaringClass().getPackageName()) - && !Modifier.isPublic(implInfo.getModifiers()); + useImplMethodHandle = !Modifier.isPublic(implInfo.getModifiers()) && + !VerifyAccess.isSamePackage(implClass, implInfo.getDeclaringClass()); cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { 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 79c59ab1d6c..64698d94a00 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4739,23 +4739,24 @@ static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodTy if (newType.returnType() != oldType.returnType()) throw newIllegalArgumentException("return types do not match", oldType, newType); - if (reorder.length == oldType.parameterCount()) { - int limit = newType.parameterCount(); - boolean bad = false; - for (int j = 0; j < reorder.length; j++) { - int i = reorder[j]; - if (i < 0 || i >= limit) { - bad = true; break; - } - Class src = newType.parameterType(i); - Class dst = oldType.parameterType(j); - if (src != dst) - throw newIllegalArgumentException("parameter types do not match after reorder", - oldType, newType); + if (reorder.length != oldType.parameterCount()) + throw newIllegalArgumentException("old type parameter count and reorder array length do not match", + oldType, Arrays.toString(reorder)); + + int limit = newType.parameterCount(); + for (int j = 0; j < reorder.length; j++) { + int i = reorder[j]; + if (i < 0 || i >= limit) { + throw newIllegalArgumentException("index is out of bounds for new type", + i, newType); } - if (!bad) return true; + Class src = newType.parameterType(i); + Class dst = oldType.parameterType(j); + if (src != dst) + throw newIllegalArgumentException("parameter types do not match after reorder", + oldType, newType); } - throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); + return true; } /** diff --git a/src/java.base/share/classes/java/lang/reflect/RecordComponent.java b/src/java.base/share/classes/java/lang/reflect/RecordComponent.java index 225a0999f17..7079f3d28f7 100644 --- a/src/java.base/share/classes/java/lang/reflect/RecordComponent.java +++ b/src/java.base/share/classes/java/lang/reflect/RecordComponent.java @@ -38,23 +38,14 @@ import java.util.Objects; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A {@code RecordComponent} provides information about, and dynamic access to, a * component of a record class. * * @see Class#getRecordComponents() * @see java.lang.Record * @jls 8.10 Record Types - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) public final class RecordComponent implements AnnotatedElement { // declaring class private Class clazz; diff --git a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java index f1115b6c36d..ad50a002f71 100644 --- a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java +++ b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java @@ -38,23 +38,14 @@ import java.util.Objects; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Bootstrap methods for state-driven implementations of core methods, * including {@link Object#equals(Object)}, {@link Object#hashCode()}, and * {@link Object#toString()}. These methods may be used, for example, by * Java compiler implementations to implement the bodies of {@link Object} * methods for record classes. * - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) public class ObjectMethods { private ObjectMethods() { } diff --git a/src/java.base/share/classes/java/net/NetPermission.java b/src/java.base/share/classes/java/net/NetPermission.java index d4f4dfd4d17..23055e5b8d2 100644 --- a/src/java.base/share/classes/java/net/NetPermission.java +++ b/src/java.base/share/classes/java/net/NetPermission.java @@ -66,6 +66,16 @@ * * * + * accessUnixDomainSocket + * The ability to accept, bind, connect or get the local address + * of a Unix Domain socket. + * + * Malicious code could connect to local processes using Unix domain sockets + * or impersonate local processes, by binding to the same pathnames (assuming they + * have the required Operating System permissions. + * + * + * * getCookieHandler * The ability to get the cookie handler that processes highly * security sensitive cookie information for an Http session. diff --git a/src/java.base/share/classes/java/net/StandardProtocolFamily.java b/src/java.base/share/classes/java/net/StandardProtocolFamily.java index 25aaed4c81c..c90a3fcf012 100644 --- a/src/java.base/share/classes/java/net/StandardProtocolFamily.java +++ b/src/java.base/share/classes/java/net/StandardProtocolFamily.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,5 +41,11 @@ public enum StandardProtocolFamily implements ProtocolFamily { /** * Internet Protocol Version 6 (IPv6) */ - INET6 + INET6, + + /** + * Unix domain (Local) interprocess communication. + * @since 16 + */ + UNIX } diff --git a/src/java.base/share/classes/java/net/UnixDomainSocketAddress.java b/src/java.base/share/classes/java/net/UnixDomainSocketAddress.java new file mode 100644 index 00000000000..d1d718fe1a1 --- /dev/null +++ b/src/java.base/share/classes/java/net/UnixDomainSocketAddress.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.net.SocketAddress; +import java.nio.channels.SocketChannel; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; + +/** + * A Unix domain socket address. + * A Unix domain socket address encapsulates a file-system path that Unix domain sockets + * bind or connect to. + * + *

An unnamed {@code UnixDomainSocketAddress} has + * an empty path. The local address of a {@link SocketChannel} to a Unix domain socket + * that is automatically or implicitly bound will be unnamed. + * + *

{@link Path} objects used to create instances of this class must be obtained + * from the {@linkplain FileSystems#getDefault system-default} file system. + * + * @see java.nio.channels.SocketChannel + * @see java.nio.channels.ServerSocketChannel + * @since 16 + */ +public final class UnixDomainSocketAddress extends SocketAddress { + @java.io.Serial + static final long serialVersionUID = 92902496589351288L; + + private final transient Path path; + + /** + * A serial proxy for all {@link UnixDomainSocketAddress} instances. + * It captures the file path name and reconstructs using the public static + * {@link #of(String) factory}. + * + * @serial include + */ + private static final class Ser implements Serializable { + @java.io.Serial + static final long serialVersionUID = -7955684448513979814L; + + /** + * The path name. + * @serial + */ + private final String pathname; + + Ser(String pathname) { + this.pathname = pathname; + } + + /** + * Creates a {@link UnixDomainSocketAddress} instance, by an invocation + * of the {@link #of(String) factory} method passing the path name. + * @return a UnixDomainSocketAddress + */ + @java.io.Serial + private Object readResolve() { + return UnixDomainSocketAddress.of(pathname); + } + } + + /** + * Returns a + * + * Ser containing the path name of this instance. + * + * @return a {@link Ser} + * representing the path name of this instance + */ + @java.io.Serial + private Object writeReplace() throws ObjectStreamException { + return new Ser(path.toString()); + } + + /** + * Throws InvalidObjectException, always. + * @param s the stream + * @throws java.io.InvalidObjectException always + */ + @java.io.Serial + private void readObject(java.io.ObjectInputStream s) + throws java.io.InvalidObjectException + { + throw new java.io.InvalidObjectException("Proxy required"); + } + + /** + * Throws InvalidObjectException, always. + * @throws java.io.InvalidObjectException always + */ + @java.io.Serial + private void readObjectNoData() + throws java.io.InvalidObjectException + { + throw new java.io.InvalidObjectException("Proxy required"); + } + + private UnixDomainSocketAddress(Path path) { + this.path = path; + } + + /** + * Creates a UnixDomainSocketAddress from the given path string. + * + * @param pathname + * The path string, which can be empty + * + * @return A UnixDomainSocketAddress + * + * @throws InvalidPathException + * If the path cannot be converted to a Path + * + * @throws NullPointerException if pathname is {@code null} + */ + public static UnixDomainSocketAddress of(String pathname) { + return of(Path.of(pathname)); + } + + /** + * Creates a UnixDomainSocketAddress for the given path. + * + * @param path + * The path to the socket, which can be empty + * + * @return A UnixDomainSocketAddress + * + * @throws IllegalArgumentException + * If the path is not associated with the default file system + * + * @throws NullPointerException if path is {@code null} + */ + public static UnixDomainSocketAddress of(Path path) { + FileSystem fs = path.getFileSystem(); + if (fs != FileSystems.getDefault()) { + throw new IllegalArgumentException(); + } + if (fs.getClass().getModule() != Object.class.getModule()) { + throw new IllegalArgumentException(); + } + return new UnixDomainSocketAddress(path); + } + + /** + * Returns this address's path. + * + * @return this address's path + */ + public Path getPath() { + return path; + } + + /** + * Returns the hash code of this {@code UnixDomainSocketAddress} + */ + @Override + public int hashCode() { + return path.hashCode(); + } + + /** + * Compares this address with another object. + * + * @return true if the path fields are equal + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof UnixDomainSocketAddress)) + return false; + UnixDomainSocketAddress that = (UnixDomainSocketAddress)o; + return this.path.equals(that.path); + } + + /** + * Returns a string representation of this {@code UnixDomainSocketAddress}. + * + * @return this address's path which may be empty for an unnamed address + */ + @Override + public String toString() { + return path.toString(); + } +} diff --git a/src/java.base/share/classes/java/nio/channels/DatagramChannel.java b/src/java.base/share/classes/java/nio/channels/DatagramChannel.java index 2838bce939b..18dac3f4b3d 100644 --- a/src/java.base/share/classes/java/nio/channels/DatagramChannel.java +++ b/src/java.base/share/classes/java/nio/channels/DatagramChannel.java @@ -150,6 +150,9 @@ protected DatagramChannel(SelectorProvider provider) { * * @throws IOException * If an I/O error occurs + * + * @see + * java.net.preferIPv4Stack system property */ public static DatagramChannel open() throws IOException { return SelectorProvider.provider().openDatagramChannel(); @@ -169,6 +172,9 @@ public static DatagramChannel open() throws IOException { * java.nio.channels.spi.SelectorProvider} object. The channel will not be * connected. * + * @apiNote Unix domain sockets + * are not supported by DatagramChannel. + * * @param family * The protocol family * @@ -182,6 +188,9 @@ public static DatagramChannel open() throws IOException { * @throws IOException * If an I/O error occurs * + * @see + * java.net.preferIPv4Stack system property + * * @since 1.7 */ public static DatagramChannel open(ProtocolFamily family) throws IOException { @@ -629,5 +638,4 @@ public final long write(ByteBuffer[] srcs) throws IOException { */ @Override public abstract SocketAddress getLocalAddress() throws IOException; - } diff --git a/src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java b/src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java index 8beecb3ebaf..c3b541f536e 100644 --- a/src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java +++ b/src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java @@ -26,10 +26,12 @@ package java.nio.channels; import java.io.IOException; +import java.net.NetPermission; import java.net.ProtocolFamily; import java.net.ServerSocket; import java.net.SocketOption; import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.channels.spi.AbstractSelectableChannel; import java.nio.channels.spi.SelectorProvider; import static java.util.Objects.requireNonNull; @@ -37,16 +39,20 @@ /** * A selectable channel for stream-oriented listening sockets. * - *

A server-socket channel is created by invoking the {@link #open() open} - * method of this class. It is not possible to create a channel for an arbitrary, - * pre-existing {@link ServerSocket}. A newly-created server-socket channel is - * open but not yet bound. An attempt to invoke the {@link #accept() accept} - * method of an unbound server-socket channel will cause a {@link NotYetBoundException} + *

A server-socket channel is created by invoking one of the {@code open} + * methods of this class. The no-arg {@link #open() open} method opens a server-socket + * channel for an Internet protocol socket. The {@link #open(ProtocolFamily)} + * method is used to open a server-socket channel for a socket of a specified + * protocol family. It is not possible to create a channel for an arbitrary, + * pre-existing socket. A newly-created server-socket channel is open but not yet + * bound. An attempt to invoke the {@link #accept() accept} method of an + * unbound server-socket channel will cause a {@link NotYetBoundException} * to be thrown. A server-socket channel can be bound by invoking one of the - * {@link #bind(java.net.SocketAddress,int) bind} methods defined by this class. + * {@link #bind(java.net.SocketAddress, int) bind} methods defined by this class. * *

Socket options are configured using the {@link #setOption(SocketOption,Object) - * setOption} method. Server-socket channels support the following options: + * setOption} method. Server-socket channels for Internet protocol sockets + * support the following options: *

* * @@ -68,7 +74,27 @@ * *
Socket options
*
- * Additional (implementation specific) options may also be supported. + * + *

Server-socket channels for Unix domain sockets support: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Socket options
Option NameDescription
{@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
+ *
+ * + *

Additional (implementation specific) options may also be supported. * *

Server-socket channels are safe for use by multiple concurrent threads. *

@@ -94,7 +120,7 @@ protected ServerSocketChannel(SelectorProvider provider) { } /** - * Opens a server-socket channel. + * Opens a server-socket channel for an Internet protocol socket. * *

The new channel is created by invoking the {@link * java.nio.channels.spi.SelectorProvider#openServerSocketChannel @@ -110,13 +136,16 @@ protected ServerSocketChannel(SelectorProvider provider) { * * @throws IOException * If an I/O error occurs + * + * @see + * java.net.preferIPv4Stack system property */ public static ServerSocketChannel open() throws IOException { return SelectorProvider.provider().openServerSocketChannel(); } /** - * Opens a server-socket channel.The {@code family} parameter specifies the + * Opens a server-socket channel. The {@code family} parameter specifies the * {@link ProtocolFamily protocol family} of the channel's socket. * *

The new channel is created by invoking the {@link @@ -137,6 +166,9 @@ public static ServerSocketChannel open() throws IOException { * @throws IOException * If an I/O error occurs * + * @see + * java.net.preferIPv4Stack system property + * * @since 15 */ public static ServerSocketChannel open(ProtocolFamily family) throws IOException { @@ -180,8 +212,7 @@ public final int validOps() { * @throws ClosedChannelException {@inheritDoc} * @throws IOException {@inheritDoc} * @throws SecurityException - * If a security manager has been installed and its {@link - * SecurityManager#checkListen checkListen} method denies the + * If a security manager has been installed and it denies the * operation * * @since 1.7 @@ -197,8 +228,8 @@ public final ServerSocketChannel bind(SocketAddress local) * listen for connections. * *

This method is used to establish an association between the socket and - * a local address. Once an association is established then the socket remains - * bound until the channel is closed. + * a local address. For Internet protocol sockets, once an association + * is established then the socket remains bound until the channel is closed. * *

The {@code backlog} parameter is the maximum number of pending * connections on the socket. Its exact semantics are implementation specific. @@ -207,9 +238,25 @@ public final ServerSocketChannel bind(SocketAddress local) * the value {@code 0}, or a negative value, then an implementation specific * default is used. * + * @apiNote + * Binding a server socket channel for a Unix Domain socket, creates a + * file corresponding to the file path in the {@link UnixDomainSocketAddress}. + * This file persists after the channel is closed, and must be removed before + * another socket can bind to the same name. Binding to a {@code null} address + * causes the socket to be automatically bound to some unique file + * in a system temporary location. The associated socket file also persists + * after the channel is closed. Its name can be obtained from the channel's + * local socket address. + * + * @implNote + * Each platform enforces an implementation specific, maximum length for the + * name of a Unix Domain socket. This limitation is enforced when a + * channel is bound. The maximum length is typically close to and generally + * not less than 100 bytes. + * * @param local - * The address to bind the socket, or {@code null} to bind to an - * automatically assigned socket address + * The address to bind the socket, or {@code null} to bind to + * an automatically assigned socket address * @param backlog * The maximum number of pending connections * @@ -225,8 +272,10 @@ public final ServerSocketChannel bind(SocketAddress local) * If some other I/O error occurs * @throws SecurityException * If a security manager has been installed and its {@link - * SecurityManager#checkListen checkListen} method denies the - * operation + * SecurityManager#checkListen checkListen} method denies + * the operation for an Internet protocol socket address, + * or for a Unix domain socket address if it denies + * {@link NetPermission}{@code("accessUnixDomainSocket")}. * * @since 1.7 */ @@ -251,6 +300,9 @@ public abstract ServerSocketChannel setOption(SocketOption name, T value) * declared in the {@link java.net.ServerSocket} class.

* * @return A server socket associated with this channel + * + * @throws UnsupportedOperationException + * If the channel's socket is not an Internet protocol socket */ public abstract ServerSocket socket(); @@ -265,13 +317,15 @@ public abstract ServerSocketChannel setOption(SocketOption name, T value) *

The socket channel returned by this method, if any, will be in * blocking mode regardless of the blocking mode of this channel. * - *

This method performs exactly the same security checks as the {@link - * java.net.ServerSocket#accept accept} method of the {@link - * java.net.ServerSocket} class. That is, if a security manager has been - * installed then for each new connection this method verifies that the - * address and port number of the connection's remote endpoint are - * permitted by the security manager's {@link - * java.lang.SecurityManager#checkAccept checkAccept} method.

+ *

If bound to an Internet protocol socket address, this method + * performs exactly the same security checks as the {@link + * java.net.ServerSocket#accept accept} method of the {@link java.net.ServerSocket} + * class. That is, if a security manager has been installed then for each + * new connection this method verifies that the address and port number + * of the connection's remote endpoint are permitted by the security + * manager's {@link java.lang.SecurityManager#checkAccept checkAccept} + * method. If bound to a Unix Domain socket address, this method checks + * {@link NetPermission}{@code ("accessUnixDomainSocket")}. * * @return The socket channel for the new connection, * or {@code null} if this channel is in non-blocking mode @@ -305,7 +359,7 @@ public abstract ServerSocketChannel setOption(SocketOption name, T value) /** * {@inheritDoc} - *

+ * * If there is a security manager set, its {@code checkConnect} method is * called with the local address and {@code -1} as its arguments to see * if the operation is allowed. If the operation is not allowed, @@ -313,9 +367,16 @@ public abstract ServerSocketChannel setOption(SocketOption name, T value) * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the * local port of the channel's socket is returned. * + *

Where the channel is bound to a Unix Domain socket address, the socket + * address is a {@link UnixDomainSocketAddress}. If there is a security manager + * set, its {@link SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method is called with {@link NetPermission}{@code + * ("accessUnixDomainSocket")}. If the operation is not allowed an unnamed + * {@link UnixDomainSocketAddress} is returned. + * * @return The {@code SocketAddress} that the socket is bound to, or the - * {@code SocketAddress} representing the loopback address if - * denied by the security manager, or {@code null} if the + * {@code SocketAddress} representing the loopback address or empty + * path if denied by the security manager, or {@code null} if the * channel's socket is not bound * * @throws ClosedChannelException {@inheritDoc} @@ -323,5 +384,4 @@ public abstract ServerSocketChannel setOption(SocketOption name, T value) */ @Override public abstract SocketAddress getLocalAddress() throws IOException; - } diff --git a/src/java.base/share/classes/java/nio/channels/SocketChannel.java b/src/java.base/share/classes/java/nio/channels/SocketChannel.java index d97ebc681c7..560440744f6 100644 --- a/src/java.base/share/classes/java/nio/channels/SocketChannel.java +++ b/src/java.base/share/classes/java/nio/channels/SocketChannel.java @@ -26,10 +26,14 @@ package java.nio.channels; import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.NetPermission; import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; import java.net.Socket; import java.net.SocketOption; import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.spi.AbstractSelectableChannel; import java.nio.channels.spi.SelectorProvider; @@ -38,15 +42,18 @@ /** * A selectable channel for stream-oriented connecting sockets. * - *

A socket channel is created by invoking one of the {@link #open open} - * methods of this class. It is not possible to create a channel for an arbitrary, - * pre-existing socket. A newly-created socket channel is open but not yet - * connected. An attempt to invoke an I/O operation upon an unconnected - * channel will cause a {@link NotYetConnectedException} to be thrown. A - * socket channel can be connected by invoking its {@link #connect connect} - * method; once connected, a socket channel remains connected until it is - * closed. Whether or not a socket channel is connected may be determined by - * invoking its {@link #isConnected isConnected} method. + *

A socket channel is created by invoking one of the {@code open} methods of + * this class. The no-arg {@link #open() open} method opens a socket channel + * for an Internet protocol socket. The {@link #open(ProtocolFamily)} + * method is used to open a socket channel for a socket of a specified protocol + * family. It is not possible to create a channel for an arbitrary, pre-existing + * socket. A newly-created socket channel is open but not yet connected. An + * attempt to invoke an I/O operation upon an unconnected channel will cause a + * {@link NotYetConnectedException} to be thrown. A socket channel can be + * connected by invoking its {@link #connect connect} method; once connected, + * a socket channel remains connected until it is closed. Whether or not a + * socket channel is connected may be determined by invoking its {@link #isConnected() + * isConnected} method. * *

Socket channels support non-blocking connection: A socket * channel may be created and the process of establishing the link to the @@ -55,7 +62,7 @@ * Whether or not a connection operation is in progress may be determined by * invoking the {@link #isConnectionPending isConnectionPending} method. * - *

Socket channels support asynchronous shutdown, which is similar + *

Socket channels support asynchronous shutdown, which is similar * to the asynchronous close operation specified in the {@link Channel} class. * If the input side of a socket is shut down by one thread while another * thread is blocked in a read operation on the socket's channel, then the read @@ -66,7 +73,8 @@ * AsynchronousCloseException}. * *

Socket options are configured using the {@link #setOption(SocketOption,Object) - * setOption} method. Socket channels support the following options: + * setOption} method. Socket channels for Internet protocol sockets support + * following options: *

* * @@ -105,7 +113,36 @@ * *
Socket options
*
- * Additional (implementation specific) options may also be supported. + * + *

Socket channels for Unix domain sockets support: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Socket options
Option NameDescription
{@link java.net.StandardSocketOptions#SO_SNDBUF SO_SNDBUF} The size of the socket send buffer
{@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
{@link java.net.StandardSocketOptions#SO_LINGER SO_LINGER} Linger on close if data is present (when configured in blocking mode + * only)
+ *
+ * + *

Additional (implementation specific) options may also be supported. * *

Socket channels are safe for use by multiple concurrent threads. They * support concurrent reading and writing, though at most one thread may be @@ -136,7 +173,7 @@ protected SocketChannel(SelectorProvider provider) { } /** - * Opens a socket channel. + * Opens a socket channel for an Internet protocol socket. * *

The new channel is created by invoking the {@link * java.nio.channels.spi.SelectorProvider#openSocketChannel @@ -147,6 +184,9 @@ protected SocketChannel(SelectorProvider provider) { * * @throws IOException * If an I/O error occurs + * + * @see + * java.net.preferIPv4Stack system property */ public static SocketChannel open() throws IOException { return SelectorProvider.provider().openSocketChannel(); @@ -174,6 +214,9 @@ public static SocketChannel open() throws IOException { * @throws IOException * If an I/O error occurs * + * @see + * java.net.preferIPv4Stack system property + * * @since 15 */ public static SocketChannel open(ProtocolFamily family) throws IOException { @@ -183,10 +226,16 @@ public static SocketChannel open(ProtocolFamily family) throws IOException { /** * Opens a socket channel and connects it to a remote address. * - *

This convenience method works as if by invoking the {@link #open()} - * method, invoking the {@link #connect(SocketAddress) connect} method upon - * the resulting socket channel, passing it {@code remote}, and then - * returning that channel.

+ *

If the remote address is an {@link InetSocketAddress} then this + * method works as if by invoking the {@link #open()} method, invoking the + * {@link #connect(SocketAddress) connect} method upon the resulting socket + * channel, passing it {@code remote}, and then returning that channel. + * + *

If the remote address is a {@link UnixDomainSocketAddress} then this + * works by invoking the {@link #open(ProtocolFamily)} method with {@link + * StandardProtocolFamily#UNIX} as parameter, invoking the {@link + * #connect(SocketAddress) connect} method upon the resulting socket channel, + * passing it {@code remote}, then returning that channel.

* * @param remote * The remote address to which the new channel is to be connected @@ -204,7 +253,8 @@ public static SocketChannel open(ProtocolFamily family) throws IOException { * interrupt status * * @throws UnresolvedAddressException - * If the given remote address is not fully resolved + * If the given remote address is an InetSocketAddress that is not fully + * resolved * * @throws UnsupportedAddressTypeException * If the type of the given remote address is not supported @@ -215,11 +265,22 @@ public static SocketChannel open(ProtocolFamily family) throws IOException { * * @throws IOException * If some other I/O error occurs + * + * @see + * java.net.preferIPv4Stack system property */ public static SocketChannel open(SocketAddress remote) throws IOException { - SocketChannel sc = open(); + SocketChannel sc; + requireNonNull(remote); + if (remote instanceof InetSocketAddress) + sc = open(); + else if (remote instanceof UnixDomainSocketAddress) + sc = open(StandardProtocolFamily.UNIX); + else + throw new UnsupportedAddressTypeException(); + try { sc.connect(remote); } catch (Throwable x) { @@ -255,6 +316,38 @@ public final int validOps() { // -- Socket-specific operations -- /** + * Binds the channel's socket to a local address. + * + *

This method is used to establish an association between the socket + * and a local address. For Internet Protocol sockets, once an + * association is established then the socket remains bound until the + * channel is closed. If the {@code local} parameter has the value {@code + * null} then the socket will be bound to an address that is assigned + * automatically. + * + * @apiNote + * Binding a socket channel to a Unix Domain socket creates a file + * corresponding to the file path in the {@link UnixDomainSocketAddress}. This + * file persists after the channel is closed, and must be removed before + * another socket can bind to the same name. If a socket channel to a Unix + * Domain socket is implicitly bound by connecting it without calling + * bind first, then its socket is + * unnamed + * with no corresponding socket file in the file-system. If a socket channel + * to a Unix Domain socket is automatically bound by calling {@code + * bind(null)} this results in an unnamed socket also. + * + * @implNote + * Each platform enforces an implementation specific maximum length for the + * name of a Unix Domain socket. This limitation is enforced when a + * channel is bound. The maximum length is typically close to and generally + * not less than 100 bytes. + * + * @param local The address to bind the socket, or {@code null} to bind + * the socket to an automatically assigned socket address + * + * @return This channel + * * @throws ConnectionPendingException * If a non-blocking connect operation is already in progress on * this channel @@ -263,9 +356,11 @@ public final int validOps() { * @throws ClosedChannelException {@inheritDoc} * @throws IOException {@inheritDoc} * @throws SecurityException - * If a security manager has been installed and its - * {@link SecurityManager#checkListen checkListen} method denies - * the operation + * If a security manager has been installed and its {@link + * SecurityManager#checkListen checkListen} method denies + * the operation for an Internet protocol socket address, + * or for a Unix domain socket address if it denies + * {@link NetPermission}{@code("accessUnixDomainSocket")}. * * @since 1.7 */ @@ -329,10 +424,10 @@ public abstract SocketChannel setOption(SocketOption name, T value) /** * Retrieves a socket associated with this channel. * - *

The returned object will not declare any public methods that are not - * declared in the {@link java.net.Socket} class.

- * * @return A socket associated with this channel + * + * @throws UnsupportedOperationException + * If the channel's socket is not an Internet protocol socket */ public abstract Socket socket(); @@ -368,12 +463,19 @@ public abstract SocketChannel setOption(SocketOption name, T value) * method will block until the connection is established or an I/O error * occurs. * - *

This method performs exactly the same security checks as the {@link - * java.net.Socket} class. That is, if a security manager has been + *

For channels to Internet protocol sockets, this method performs + * exactly the same security checks as the {@link java.net.Socket} class. + * That is, if a security manager has been * installed then this method verifies that its {@link * java.lang.SecurityManager#checkConnect checkConnect} method permits * connecting to the address and port number of the given remote endpoint. * + *

For channels to Unix Domain sockets, this method checks + * {@link java.net.NetPermission NetPermission}{@code + * ("accessUnixDomainSocket")} with the security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method. + * *

This method may be invoked at any time. If a read or write * operation upon this channel is invoked while an invocation of this * method is in progress then that operation will first block until this @@ -409,7 +511,7 @@ public abstract SocketChannel setOption(SocketOption name, T value) * interrupt status * * @throws UnresolvedAddressException - * If the given remote address is not fully resolved + * If the given remote address is an InetSocketAddress that is not fully resolved * * @throws UnsupportedAddressTypeException * If the type of the given remote address is not supported @@ -477,9 +579,12 @@ public abstract SocketChannel setOption(SocketOption name, T value) /** * Returns the remote address to which this channel's socket is connected. * - *

Where the channel is bound and connected to an Internet Protocol - * socket address then the return value from this method is of type {@link - * java.net.InetSocketAddress}. + *

Where the channel's socket is bound and connected to an Internet + * Protocol socket address then the return value is of type + * {@link java.net.InetSocketAddress}. + * + *

Where the channel's socket is bound and connected to a Unix Domain + * socket address, the returned address is a {@link UnixDomainSocketAddress}. * * @return The remote address; {@code null} if the channel's socket is not * connected @@ -539,7 +644,7 @@ public final long write(ByteBuffer[] srcs) throws IOException { /** * {@inheritDoc} - *

+ * * If there is a security manager set, its {@code checkConnect} method is * called with the local address and {@code -1} as its arguments to see * if the operation is allowed. If the operation is not allowed, @@ -547,9 +652,16 @@ public final long write(ByteBuffer[] srcs) throws IOException { * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the * local port of the channel's socket is returned. * + *

Where the channel is bound to a Unix Domain socket address, the socket + * address is a {@link UnixDomainSocketAddress}. If there is a security manager + * set, its {@link SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method is called with {@link NetPermission}{@code + * ("accessUnixDomainSocket")}. If the operation is not allowed an unnamed + * {@link UnixDomainSocketAddress} is returned. + * * @return The {@code SocketAddress} that the socket is bound to, or the - * {@code SocketAddress} representing the loopback address if - * denied by the security manager, or {@code null} if the + * {@code SocketAddress} representing the loopback address or empty + * path if denied by the security manager, or {@code null} if the * channel's socket is not bound * * @throws ClosedChannelException {@inheritDoc} @@ -557,5 +669,4 @@ public final long write(ByteBuffer[] srcs) throws IOException { */ @Override public abstract SocketAddress getLocalAddress() throws IOException; - } diff --git a/src/java.base/share/classes/java/nio/channels/package-info.java b/src/java.base/share/classes/java/nio/channels/package-info.java index 0dc410ddd76..ed9565d8172 100644 --- a/src/java.base/share/classes/java/nio/channels/package-info.java +++ b/src/java.base/share/classes/java/nio/channels/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,6 +241,28 @@ * If a channel needs an associated socket then a socket will be created as a side * effect of this operation. * + *

{@link java.nio.channels.DatagramChannel}, + * {@link java.nio.channels.SocketChannel} and + * {@link java.nio.channels.ServerSocketChannel}s can be created + * with different {@link java.net.ProtocolFamily protocol families}. The standard + * family types are specified in {@link java.net.StandardProtocolFamily}. + * + *

Channels for Internet Protocol sockets are created using the + * {@link java.net.StandardProtocolFamily#INET INET} or {@link + * java.net.StandardProtocolFamily#INET6 INET6} protocol families. Internet + * Protocol sockets support network communication using TCP and UDP and are + * addressed using {@link java.net.InetSocketAddress}es which encapsulate an IP + * address and port number. Internet Protocol sockets are also the default + * type created, when a protocol family is not specified in the channel factory + * creation method. + * + *

Channels for Unix Domain sockets are created + * using the {@link java.net.StandardProtocolFamily#UNIX UNIX} protocol family. + * Unix Domain sockets support local inter-process + * communication on the same host, and are addressed using {@link + * java.net.UnixDomainSocketAddress}es which encapsulate a filesystem pathname + * on the local system. + * *

The implementation of selectors, selectable channels, and selection keys * can be replaced by "plugging in" an alternative definition or instance of the * {@link java.nio.channels.spi.SelectorProvider} class defined in the {@link diff --git a/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java b/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java index e59533a0148..3b3277469b8 100644 --- a/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java +++ b/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java @@ -268,34 +268,38 @@ public abstract SocketChannel openSocketChannel() * associated network port. In this example, the process that is started, * inherits a channel representing a network socket. * - *

In cases where the inherited channel represents a network socket - * then the {@link java.nio.channels.Channel Channel} type returned + *

In cases where the inherited channel is for an Internet protocol + * socket then the {@link Channel Channel} type returned * by this method is determined as follows: * *

    * - *
  • If the inherited channel represents a stream-oriented connected - * socket then a {@link java.nio.channels.SocketChannel SocketChannel} is - * returned. The socket channel is, at least initially, in blocking - * mode, bound to a socket address, and connected to a peer. + *

  • If the inherited channel is for a stream-oriented connected + * socket then a {@link SocketChannel SocketChannel} is returned. The + * socket channel is, at least initially, in blocking mode, bound + * to a socket address, and connected to a peer. *

  • * - *
  • If the inherited channel represents a stream-oriented listening - * socket then a {@link java.nio.channels.ServerSocketChannel - * ServerSocketChannel} is returned. The server-socket channel is, at - * least initially, in blocking mode, and bound to a socket address. + *

  • If the inherited channel is for a stream-oriented listening + * socket then a {@link ServerSocketChannel ServerSocketChannel} is returned. + * The server-socket channel is, at least initially, in blocking mode, + * and bound to a socket address. *

  • * - *
  • If the inherited channel is a datagram-oriented socket - * then a {@link java.nio.channels.DatagramChannel DatagramChannel} is - * returned. The datagram channel is, at least initially, in blocking - * mode, and bound to a socket address. + *

  • If the inherited channel is a datagram-oriented socket then a + * {@link DatagramChannel DatagramChannel} is returned. The datagram channel + * is, at least initially, in blocking mode, and bound to a socket address. *

  • * *
* - *

In addition to the network-oriented channels described, this method - * may return other kinds of channels in the future. + *

In cases where the inherited channel is for a Unix domain + * socket then the {@link Channel} type returned is the same as for + * Internet protocol sockets as described above, except that + * datagram-oriented sockets are not supported. + * + *

In addition to the two types of socket just described, this method + * may return other types in the future. * *

The first invocation of this method creates the channel that is * returned. Subsequent invocations of this method return the same diff --git a/src/java.base/share/classes/java/nio/file/TempFileHelper.java b/src/java.base/share/classes/java/nio/file/TempFileHelper.java index cccc14f880e..860838751bf 100644 --- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java +++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,7 @@ import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import static java.nio.file.attribute.PosixFilePermission.*; -import sun.security.action.GetPropertyAction; - +import jdk.internal.util.StaticProperty; /** * Helper class to support creation of temporary files and directories with @@ -45,8 +44,7 @@ class TempFileHelper { private TempFileHelper() { } // temporary directory location - private static final Path tmpdir = - Path.of(GetPropertyAction.privilegedGetProperty("java.io.tmpdir")); + private static final Path tmpdir = Path.of(StaticProperty.javaIoTmpDir()); private static final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index c7a09e56232..521eca47fd4 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1556,11 +1556,11 @@ public DateTimeFormatterBuilder appendOptional(DateTimeFormatter formatter) { * GGGGG 5 appendText(ChronoField.ERA, TextStyle.NARROW) * * u 1 appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL) - * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2000) + * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2, 2000) * uuu 3 appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL) * u..u 4..n appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD) * y 1 appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL) - * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000) + * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, 2000) * yyy 3 appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL) * y..y 4..n appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD) * Y 1 append special localized WeekFields element for numeric week-based-year diff --git a/src/java.base/share/classes/java/util/Timer.java b/src/java.base/share/classes/java/util/Timer.java index 7c47d0c7135..95577f29b8d 100644 --- a/src/java.base/share/classes/java/util/Timer.java +++ b/src/java.base/share/classes/java/util/Timer.java @@ -120,7 +120,7 @@ protected void finalize() throws Throwable { /** * This ID is used to generate thread names. */ - private static final AtomicInteger nextSerialNumber = new AtomicInteger(0); + private static final AtomicInteger nextSerialNumber = new AtomicInteger(); private static int serialNumber() { return nextSerialNumber.getAndIncrement(); } diff --git a/src/java.base/share/classes/java/util/stream/AbstractShortCircuitTask.java b/src/java.base/share/classes/java/util/stream/AbstractShortCircuitTask.java index bbf09f03b14..d59fcfa600c 100644 --- a/src/java.base/share/classes/java/util/stream/AbstractShortCircuitTask.java +++ b/src/java.base/share/classes/java/util/stream/AbstractShortCircuitTask.java @@ -68,7 +68,7 @@ abstract class AbstractShortCircuitTask helper, Spliterator spliterator) { super(helper, spliterator); - sharedResult = new AtomicReference<>(null); + sharedResult = new AtomicReference<>(); } /** diff --git a/src/java.base/share/classes/jdk/internal/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/PreviewFeature.java index 2f62a9c48a6..5624ead42d9 100644 --- a/src/java.base/share/classes/jdk/internal/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/PreviewFeature.java @@ -62,6 +62,11 @@ public enum Feature { // JDK 15. Since the JDK 14 codebase uses the enum constant, it is // necessary for PreviewFeature in JDK 15 to declare the enum constant. TEXT_BLOCKS, + // The RECORDS enum constant is not used in the JDK 16 codebase, but + // exists to support the bootcycle build of JDK 16. The bootcycle build + // of JDK 16 is performed with JDK 15 and the PreviewFeature type from + // JDK 16. Since the JDK 15 codebase uses the enum constant, it is + // necessary for PreviewFeature in JDK 16 to declare the enum constant. RECORDS, SEALED_CLASSES, ; diff --git a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java index 600fca59b6f..40f53990964 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java @@ -4541,7 +4541,8 @@ public static boolean requiresBidi(char[] text, if (0 > start || start > limit || limit > text.length) { throw new IllegalArgumentException("Value start " + start + - " is out of range 0 to " + limit); + " is out of range 0 to " + limit + ", or limit " + limit + + " is beyond the text length " + text.length); } for (int i = start; i < limit; ++i) { diff --git a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java index 4c167ff98f0..d493f6653b2 100644 --- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java +++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java @@ -47,6 +47,7 @@ public final class StaticProperty { private static final String JAVA_LIBRARY_PATH; private static final String SUN_BOOT_LIBRARY_PATH; private static final String JDK_SERIAL_FILTER; + private static final String JAVA_IO_TMPDIR; private StaticProperty() {} @@ -56,6 +57,7 @@ private StaticProperty() {} USER_HOME = getProperty(props, "user.home"); USER_DIR = getProperty(props, "user.dir"); USER_NAME = getProperty(props, "user.name"); + JAVA_IO_TMPDIR = getProperty(props, "java.io.tmpdir"); JAVA_LIBRARY_PATH = getProperty(props, "java.library.path", ""); SUN_BOOT_LIBRARY_PATH = getProperty(props, "sun.boot.library.path", ""); JDK_SERIAL_FILTER = getProperty(props, "jdk.serialFilter", null); @@ -140,6 +142,19 @@ public static String javaLibraryPath() { return JAVA_LIBRARY_PATH; } + /** + * Return the {@code java.io.tmpdir} system property. + * + * {@link SecurityManager#checkPropertyAccess} is NOT checked + * in this method. The caller of this method should take care to ensure + * that the returned property is not made accessible to untrusted code. + * + * @return the {@code java.io.tmpdir} system property + */ + public static String javaIoTmpDir() { + return JAVA_IO_TMPDIR; + } + /** * Return the {@code sun.boot.library.path} system property. * diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index d04134969c2..12ea481767e 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -270,6 +270,8 @@ jdk.incubator.foreign; exports sun.nio.cs to jdk.charsets; + exports sun.nio.fs to + jdk.net; exports sun.reflect.annotation to jdk.compiler; exports sun.reflect.generics.reflectiveObjects to diff --git a/src/java.base/share/classes/sun/net/ResourceManager.java b/src/java.base/share/classes/sun/net/ResourceManager.java index fb19671578b..abc09680ba2 100644 --- a/src/java.base/share/classes/sun/net/ResourceManager.java +++ b/src/java.base/share/classes/sun/net/ResourceManager.java @@ -62,7 +62,7 @@ public class ResourceManager { } } catch (NumberFormatException e) {} maxSockets = defmax; - numSockets = new AtomicInteger(0); + numSockets = new AtomicInteger(); } public static void beforeUdpCreate() throws SocketException { diff --git a/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java b/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java index ee77c758fe8..cdde3507929 100644 --- a/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java +++ b/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ public abstract class ExtendedSocketOptions { private final Set> datagramOptions; private final Set> clientStreamOptions; private final Set> serverStreamOptions; + private final Set> unixDomainClientOptions; /** Tells whether or not the option is supported. */ public final boolean isOptionSupported(SocketOption option) { @@ -73,6 +74,19 @@ public static Set> clientSocketOptions() { return getInstance().options0(SOCK_STREAM, false); } + /** + * Return the, possibly empty, set of extended socket options available for + * Unix domain client sockets. Note, there are no extended + * Unix domain server options. + */ + private final Set> unixDomainClientOptions() { + return unixDomainClientOptions; + } + + public static Set> unixDomainSocketOptions() { + return getInstance().unixDomainClientOptions(); + } + /** * Returns the (possibly empty) set of extended socket options for * datagram-oriented sockets. @@ -82,14 +96,22 @@ public static Set> datagramSocketOptions() { } private static boolean isDatagramOption(SocketOption option) { - return !option.name().startsWith("TCP_"); + if (option.name().startsWith("TCP_") || isUnixDomainOption(option)) { + return false; + } else { + return true; + } + } + + private static boolean isUnixDomainOption(SocketOption option) { + return option.name().equals("SO_PEERCRED"); } private static boolean isStreamOption(SocketOption option, boolean server) { - if (server && "SO_FLOW_SLA".equals(option.name())) { + if (option.name().startsWith("UDP_") || isUnixDomainOption(option)) { return false; } else { - return !option.name().startsWith("UDP_"); + return true; } } @@ -122,6 +144,7 @@ protected ExtendedSocketOptions(Set> options) { var datagramOptions = new HashSet>(); var serverStreamOptions = new HashSet>(); var clientStreamOptions = new HashSet>(); + var unixDomainClientOptions = new HashSet>(); for (var option : options) { if (isDatagramOption(option)) { datagramOptions.add(option); @@ -132,10 +155,14 @@ protected ExtendedSocketOptions(Set> options) { if (isStreamOption(option, false)) { clientStreamOptions.add(option); } + if (isUnixDomainOption(option)) { + unixDomainClientOptions.add(option); + } } this.datagramOptions = Set.copyOf(datagramOptions); this.serverStreamOptions = Set.copyOf(serverStreamOptions); this.clientStreamOptions = Set.copyOf(clientStreamOptions); + this.unixDomainClientOptions = Set.copyOf(unixDomainClientOptions); } private static volatile ExtendedSocketOptions instance; diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index 5cf7f30d7cf..442860138c5 100644 --- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,16 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Base64; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; -import java.util.TimeZone; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -289,9 +290,6 @@ public FtpDirEntry parseLine(String line) { } private class MLSxParser implements FtpDirParser { - - private SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss"); - public FtpDirEntry parseLine(String line) { String name = null; int i = line.lastIndexOf(';'); @@ -326,22 +324,14 @@ public FtpDirEntry parseLine(String line) { } s = file.getFact("Modify"); if (s != null) { - Date d = null; - try { - d = df.parse(s); - } catch (ParseException ex) { - } + Date d = parseRfc3659TimeValue(s); if (d != null) { file.setLastModified(d); } } s = file.getFact("Create"); if (s != null) { - Date d = null; - try { - d = df.parse(s); - } catch (ParseException ex) { - } + Date d = parseRfc3659TimeValue(s); if (d != null) { file.setCreated(d); } @@ -1749,18 +1739,9 @@ public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOExce } return -1; } - private static String[] MDTMformats = { - "yyyyMMddHHmmss.SSS", - "yyyyMMddHHmmss" - }; - private static SimpleDateFormat[] dateFormats = new SimpleDateFormat[MDTMformats.length]; - static { - for (int i = 0; i < MDTMformats.length; i++) { - dateFormats[i] = new SimpleDateFormat(MDTMformats[i]); - dateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT")); - } - } + private static final DateTimeFormatter RFC3659_DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss[.SSS]") + .withZone(ZoneOffset.UTC); /** * Issues the MDTM [path] command to the server to get the modification @@ -1777,21 +1758,22 @@ public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOExce public Date getLastModified(String path) throws sun.net.ftp.FtpProtocolException, IOException { issueCommandCheck("MDTM " + path); if (lastReplyCode == FtpReplyCode.FILE_STATUS) { - String s = getResponseString().substring(4); - Date d = null; - for (SimpleDateFormat dateFormat : dateFormats) { - try { - d = dateFormat.parse(s); - } catch (ParseException ex) { - } - if (d != null) { - return d; - } - } + String s = getResponseString(); + return parseRfc3659TimeValue(s.substring(4, s.length() - 1)); } return null; } + private static Date parseRfc3659TimeValue(String s) { + Date result = null; + try { + var d = ZonedDateTime.parse(s, RFC3659_DATETIME_FORMAT); + result = Date.from(d.toInstant()); + } catch (DateTimeParseException ex) { + } + return result; + } + /** * Sets the parser used to handle the directory output to the specified * one. By default the parser is set to one that can handle most FTP diff --git a/src/java.base/share/classes/sun/net/util/SocketExceptions.java b/src/java.base/share/classes/sun/net/util/SocketExceptions.java index 24f6d8e9bad..17cb5b3bfbe 100644 --- a/src/java.base/share/classes/sun/net/util/SocketExceptions.java +++ b/src/java.base/share/classes/sun/net/util/SocketExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,8 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.net.InetSocketAddress; +import java.net.UnixDomainSocketAddress; +import java.net.SocketAddress; import java.security.AccessController; import java.security.PrivilegedAction; @@ -51,11 +53,22 @@ private SocketExceptions() {} * * Only specific IOException subtypes are supported. */ - public static IOException of(IOException e, InetSocketAddress address) { - if (!enhancedExceptionText || address == null) + public static IOException of(IOException e, SocketAddress addr) { + if (!enhancedExceptionText || addr == null) { return e; - int port = address.getPort(); - String host = address.getHostString(); + } + if (addr instanceof UnixDomainSocketAddress) { + return ofUnixDomain(e, (UnixDomainSocketAddress)addr); + } else if (addr instanceof InetSocketAddress) { + return ofInet(e, (InetSocketAddress)addr); + } else { + return e; + } + } + + private static IOException ofInet(IOException e, InetSocketAddress addr) { + int port = addr.getPort(); + String host = addr.getHostString(); StringBuilder sb = new StringBuilder(); sb.append(e.getMessage()); sb.append(": "); @@ -66,6 +79,16 @@ public static IOException of(IOException e, InetSocketAddress address) { return create(e, enhancedMsg); } + private static IOException ofUnixDomain(IOException e, UnixDomainSocketAddress addr) { + String path = addr.getPath().toString(); + StringBuilder sb = new StringBuilder(); + sb.append(e.getMessage()); + sb.append(": "); + sb.append(path); + String enhancedMsg = sb.toString(); + return create(e, enhancedMsg); + } + // return a new instance of the same type with the given detail // msg, or if the type doesn't support detail msgs, return given // instance. diff --git a/src/java.base/share/classes/sun/nio/ch/Net.java b/src/java.base/share/classes/sun/nio/ch/Net.java index 1a796dff453..62bc3c9395b 100644 --- a/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/src/java.base/share/classes/sun/nio/ch/Net.java @@ -226,29 +226,31 @@ static void translateException(Exception x) /** * Returns the local address after performing a SecurityManager#checkConnect. */ - static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) { + static InetSocketAddress getRevealedLocalAddress(SocketAddress sa) { + InetSocketAddress isa = (InetSocketAddress) sa; SecurityManager sm = System.getSecurityManager(); - if (addr == null || sm == null) - return addr; - - try{ - sm.checkConnect(addr.getAddress().getHostAddress(), -1); - // Security check passed - } catch (SecurityException e) { - // Return loopback address only if security check fails - addr = getLoopbackAddress(addr.getPort()); + if (isa != null && sm != null) { + try { + sm.checkConnect(isa.getAddress().getHostAddress(), -1); + } catch (SecurityException e) { + // Return loopback address only if security check fails + isa = getLoopbackAddress(isa.getPort()); + } } - return addr; + return isa; } - static String getRevealedLocalAddressAsString(InetSocketAddress addr) { - return System.getSecurityManager() == null ? addr.toString() : - getLoopbackAddress(addr.getPort()).toString(); + static String getRevealedLocalAddressAsString(SocketAddress sa) { + InetSocketAddress isa = (InetSocketAddress) sa; + if (System.getSecurityManager() == null) { + return isa.toString(); + } else { + return getLoopbackAddress(isa.getPort()).toString(); + } } private static InetSocketAddress getLoopbackAddress(int port) { - return new InetSocketAddress(InetAddress.getLoopbackAddress(), - port); + return new InetSocketAddress(InetAddress.getLoopbackAddress(), port); } private static final InetAddress anyLocalInet4Address; @@ -574,6 +576,13 @@ static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, return connect0(preferIPv6, fd, remote, remotePort); } + static int connect(ProtocolFamily family, FileDescriptor fd, SocketAddress remote) + throws IOException + { + InetSocketAddress isa = (InetSocketAddress) remote; + return connect(family, fd, isa.getAddress(), isa.getPort()); + } + private static native int connect0(boolean preferIPv6, FileDescriptor fd, InetAddress remote, diff --git a/src/java.base/share/classes/sun/nio/ch/SelectorProviderImpl.java b/src/java.base/share/classes/sun/nio/ch/SelectorProviderImpl.java index 2fd6a984140..fc327295ed6 100644 --- a/src/java.base/share/classes/sun/nio/ch/SelectorProviderImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SelectorProviderImpl.java @@ -33,6 +33,10 @@ import java.nio.channels.SocketChannel; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; +import java.util.Objects; +import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.INET6; +import static java.net.StandardProtocolFamily.UNIX; public abstract class SelectorProviderImpl extends SelectorProvider @@ -75,11 +79,29 @@ public SocketChannel openSocketChannel() throws IOException { @Override public SocketChannel openSocketChannel(ProtocolFamily family) throws IOException { - return new SocketChannelImpl(this, family); + Objects.requireNonNull(family, "'family' is null"); + if (family == INET6 && !Net.isIPv6Available()) { + throw new UnsupportedOperationException("IPv6 not available"); + } else if (family == INET || family == INET6) { + return new SocketChannelImpl(this, family); + } else if (family == UNIX && UnixDomainSockets.isSupported()) { + return new SocketChannelImpl(this, family); + } else { + throw new UnsupportedOperationException("Protocol family not supported"); + } } @Override - public ServerSocketChannel openServerSocketChannel(ProtocolFamily family) { - return new ServerSocketChannelImpl(this, family); + public ServerSocketChannel openServerSocketChannel(ProtocolFamily family) throws IOException { + Objects.requireNonNull(family, "'family' is null"); + if (family == INET6 && !Net.isIPv6Available()) { + throw new UnsupportedOperationException("IPv6 not available"); + } else if (family == INET || family == INET6) { + return new ServerSocketChannelImpl(this, family); + } else if (family == UNIX && UnixDomainSockets.isSupported()) { + return new ServerSocketChannelImpl(this, family); + } else { + throw new UnsupportedOperationException("Protocol family not supported"); + } } } diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java index ab0e5a85a3c..6b475027ca7 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ public void bind(SocketAddress local, int backlog) throws IOException { @Override public InetAddress getInetAddress() { - InetSocketAddress local = ssc.localAddress(); + SocketAddress local = ssc.localAddress(); if (local == null) { return null; } else { @@ -103,7 +103,7 @@ public InetAddress getInetAddress() { @Override public int getLocalPort() { - InetSocketAddress local = ssc.localAddress(); + InetSocketAddress local = (InetSocketAddress) ssc.localAddress(); if (local == null) { return -1; } else { diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 06915cb6cc5..fddfca1bbcb 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,15 @@ import java.io.FileDescriptor; import java.io.IOException; +import java.net.BindException; import java.net.InetSocketAddress; import java.net.ProtocolFamily; import java.net.ServerSocket; import java.net.SocketAddress; import java.net.SocketOption; import java.net.SocketTimeoutException; -import java.net.StandardProtocolFamily; import java.net.StandardSocketOptions; +import java.net.UnixDomainSocketAddress; import java.nio.channels.AlreadyBoundException; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.ClosedChannelException; @@ -44,11 +45,15 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; +import java.nio.file.Path; import java.util.Collections; import java.util.HashSet; -import java.util.Objects; import java.util.Set; +import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; +import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.INET6; +import static java.net.StandardProtocolFamily.UNIX; import sun.net.NetHooks; import sun.net.ext.ExtendedSocketOptions; @@ -90,7 +95,7 @@ class ServerSocketChannelImpl private long thread; // Binding - private InetSocketAddress localAddress; // null => unbound + private SocketAddress localAddress; // null => unbound // set true when exclusive binding is on and SO_REUSEADDR is emulated private boolean isReuseAddress; @@ -100,47 +105,72 @@ class ServerSocketChannelImpl // -- End of fields protected by stateLock - ServerSocketChannelImpl(SelectorProvider sp) { - this(sp, Net.isIPv6Available() - ? StandardProtocolFamily.INET6 - : StandardProtocolFamily.INET); + ServerSocketChannelImpl(SelectorProvider sp) throws IOException { + this(sp, Net.isIPv6Available() ? INET6 : INET); } - ServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family) { + ServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family) + throws IOException + { super(sp); Objects.requireNonNull(family, "'family' is null"); - - if ((family != StandardProtocolFamily.INET) && - (family != StandardProtocolFamily.INET6)) { + if ((family != INET) && (family != INET6) && (family != UNIX)) { throw new UnsupportedOperationException("Protocol family not supported"); } - if (family == StandardProtocolFamily.INET6 && !Net.isIPv6Available()) { + if (family == INET6 && !Net.isIPv6Available()) { throw new UnsupportedOperationException("IPv6 not available"); } this.family = family; - this.fd = Net.serverSocket(family, true); + if (family == UNIX) { + this.fd = UnixDomainSockets.socket(); + } else { + this.fd = Net.serverSocket(family, true); + } this.fdVal = IOUtil.fdVal(fd); } - ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) + ServerSocketChannelImpl(SelectorProvider sp, + ProtocolFamily family, + FileDescriptor fd, + boolean bound) throws IOException { super(sp); - this.family = Net.isIPv6Available() - ? StandardProtocolFamily.INET6 - : StandardProtocolFamily.INET; - this.fd = fd; + if (family == UNIX) { + this.family = UNIX; + } else { + this.family = Net.isIPv6Available() ? INET6 : INET; + } + this.fd = fd; this.fdVal = IOUtil.fdVal(fd); if (bound) { synchronized (stateLock) { - localAddress = Net.localAddress(fd); + if (family == UNIX) { + localAddress = UnixDomainSockets.localAddress(fd); + } else { + localAddress = Net.localAddress(fd); + } } } } + /** + * Returns true if this channel is to a INET or INET6 socket. + */ + private boolean isNetSocket() { + return (family == INET) || (family == INET6); + } + + /** + * Returns true if this channel is to a UNIX socket. + */ + boolean isUnixSocket() { + return (family == UNIX); + } + // @throws ClosedChannelException if channel is closed private void ensureOpen() throws ClosedChannelException { if (!isOpen()) @@ -150,8 +180,13 @@ private void ensureOpen() throws ClosedChannelException { @Override public ServerSocket socket() { synchronized (stateLock) { - if (socket == null) - socket = ServerSocketAdaptor.create(this); + if (socket == null) { + if (isNetSocket()) { + socket = ServerSocketAdaptor.create(this); + } else { + throw new UnsupportedOperationException("Not supported"); + } + } return socket; } } @@ -160,9 +195,11 @@ public ServerSocket socket() { public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { ensureOpen(); - return (localAddress == null) - ? null - : Net.getRevealedLocalAddress(localAddress); + if (isUnixSocket()) { + return UnixDomainSockets.getRevealedLocalAddress(localAddress); + } else { + return Net.getRevealedLocalAddress(localAddress); + } } } @@ -178,10 +215,11 @@ public ServerSocketChannel setOption(SocketOption name, T value) synchronized (stateLock) { ensureOpen(); - - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { + if (isNetSocket() + && name == StandardSocketOptions.SO_REUSEADDR + && Net.useExclusiveBind()) { // SO_REUSEADDR emulated when using exclusive bind - isReuseAddress = (Boolean)value; + isReuseAddress = (Boolean) value; } else { // no options that require special handling Net.setSocketOption(fd, Net.UNSPEC, name, value); @@ -201,19 +239,23 @@ public T getOption(SocketOption name) synchronized (stateLock) { ensureOpen(); - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { + if (isNetSocket() + && name == StandardSocketOptions.SO_REUSEADDR + && Net.useExclusiveBind()) { // SO_REUSEADDR emulated when using exclusive bind - return (T)Boolean.valueOf(isReuseAddress); + return (T) Boolean.valueOf(isReuseAddress); + } else { + // no options that require special handling + return (T) Net.getSocketOption(fd, Net.UNSPEC, name); } - // no options that require special handling - return (T) Net.getSocketOption(fd, Net.UNSPEC, name); } } private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); + static final Set> defaultInetOptions = defaultInetOptions(); + static final Set> defaultUnixDomainOptions = defaultUnixDomainOptions(); - private static Set> defaultOptions() { + private static Set> defaultInetOptions() { HashSet> set = new HashSet<>(); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); @@ -223,11 +265,21 @@ private static Set> defaultOptions() { set.addAll(ExtendedSocketOptions.serverSocketOptions()); return Collections.unmodifiableSet(set); } + + private static Set> defaultUnixDomainOptions() { + HashSet> set = new HashSet<>(); + set.add(StandardSocketOptions.SO_RCVBUF); + return Collections.unmodifiableSet(set); + } } @Override public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; + if (isUnixSocket()) { + return DefaultOptionsHolder.defaultUnixDomainOptions; + } else { + return DefaultOptionsHolder.defaultInetOptions; + } } @Override @@ -236,23 +288,56 @@ public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOExcep ensureOpen(); if (localAddress != null) throw new AlreadyBoundException(); - InetSocketAddress isa; - if (local == null) { - isa = new InetSocketAddress(Net.anyLocalAddress(family), 0); + if (isUnixSocket()) { + localAddress = unixBind(local, backlog); } else { - isa = Net.checkAddress(local, family); + localAddress = netBind(local, backlog); } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); - NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); - Net.bind(family, fd, isa.getAddress(), isa.getPort()); - Net.listen(fd, backlog < 1 ? 50 : backlog); - localAddress = Net.localAddress(fd); } return this; } + private SocketAddress unixBind(SocketAddress local, int backlog) throws IOException { + UnixDomainSockets.checkPermission(); + if (local == null) { + // Attempt up to 10 times to find an unused name in temp directory. + // If local address supplied then bind called only once + boolean bound = false; + int attempts = 0; + while (attempts < 10 && !bound) { + try { + Path path = UnixDomainSockets.generateTempName().getPath(); + UnixDomainSockets.bind(fd, path); + bound = true; + } catch (BindException e) { } + attempts++; + } + if (!bound) + throw new BindException("Could not bind to temporary name"); + } else { + Path path = UnixDomainSockets.checkAddress(local).getPath(); + UnixDomainSockets.bind(fd, path); + } + Net.listen(fd, backlog < 1 ? 50 : backlog); + return UnixDomainSockets.localAddress(fd); + } + + private SocketAddress netBind(SocketAddress local, int backlog) throws IOException { + InetSocketAddress isa; + if (local == null) { + isa = new InetSocketAddress(Net.anyLocalAddress(family), 0); + } else { + isa = Net.checkAddress(local, family); + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkListen(isa.getPort()); + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); + Net.bind(family, fd, isa.getAddress(), isa.getPort()); + Net.listen(fd, backlog < 1 ? 50 : backlog); + return Net.localAddress(fd); + } + /** * Marks the beginning of an I/O operation that might block. * @@ -295,18 +380,18 @@ private void end(boolean blocking, boolean completed) public SocketChannel accept() throws IOException { int n = 0; FileDescriptor newfd = new FileDescriptor(); - InetSocketAddress[] isaa = new InetSocketAddress[1]; + SocketAddress[] saa = new SocketAddress[1]; acceptLock.lock(); try { boolean blocking = isBlocking(); try { begin(blocking); - n = Net.accept(this.fd, newfd, isaa); + n = implAccept(this.fd, newfd, saa); if (blocking) { while (IOStatus.okayToRetry(n) && isOpen()) { park(Net.POLLIN); - n = Net.accept(this.fd, newfd, isaa); + n = implAccept(this.fd, newfd, saa); } } } finally { @@ -318,12 +403,31 @@ public SocketChannel accept() throws IOException { } if (n > 0) { - return finishAccept(newfd, isaa[0]); + return finishAccept(newfd, saa[0]); } else { return null; } } + private int implAccept(FileDescriptor fd, FileDescriptor newfd, SocketAddress[] saa) + throws IOException + { + if (isUnixSocket()) { + UnixDomainSockets.checkPermission(); + String[] pa = new String[1]; + int n = UnixDomainSockets.accept(fd, newfd, pa); + if (n > 0) + saa[0] = UnixDomainSocketAddress.of(pa[0]); + return n; + } else { + InetSocketAddress[] issa = new InetSocketAddress[1]; + int n = Net.accept(fd, newfd, issa); + if (n > 0) + saa[0] = issa[0]; + return n; + } + } + /** * Accepts a new connection with a given timeout. This method requires the * channel to be configured in blocking mode. @@ -337,7 +441,7 @@ public SocketChannel accept() throws IOException { SocketChannel blockingAccept(long nanos) throws IOException { int n = 0; FileDescriptor newfd = new FileDescriptor(); - InetSocketAddress[] isaa = new InetSocketAddress[1]; + SocketAddress[] saa = new SocketAddress[1]; acceptLock.lock(); try { @@ -351,14 +455,14 @@ SocketChannel blockingAccept(long nanos) throws IOException { lockedConfigureBlocking(false); try { long startNanos = System.nanoTime(); - n = Net.accept(fd, newfd, isaa); + n = implAccept(fd, newfd, saa); while (n == IOStatus.UNAVAILABLE && isOpen()) { long remainingNanos = nanos - (System.nanoTime() - startNanos); if (remainingNanos <= 0) { throw new SocketTimeoutException("Accept timed out"); } park(Net.POLLIN, remainingNanos); - n = Net.accept(fd, newfd, isaa); + n = implAccept(fd, newfd, saa); } } finally { // restore socket to blocking mode (if channel is open) @@ -372,10 +476,10 @@ SocketChannel blockingAccept(long nanos) throws IOException { } assert n > 0; - return finishAccept(newfd, isaa[0]); + return finishAccept(newfd, saa[0]); } - private SocketChannel finishAccept(FileDescriptor newfd, InetSocketAddress isa) + private SocketChannel finishAccept(FileDescriptor newfd, SocketAddress sa) throws IOException { try { @@ -383,11 +487,14 @@ private SocketChannel finishAccept(FileDescriptor newfd, InetSocketAddress isa) IOUtil.configureBlocking(newfd, true); // check permitted to accept connections from the remote address - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); + if (isNetSocket()) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + InetSocketAddress isa = (InetSocketAddress) sa; + sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); + } } - return new SocketChannelImpl(provider(), family, newfd, isa); + return new SocketChannelImpl(provider(), family, newfd, sa); } catch (Exception e) { nd.close(newfd); throw e; @@ -536,7 +643,7 @@ boolean isBound() { /** * Returns the local address, or null if not bound */ - InetSocketAddress localAddress() { + SocketAddress localAddress() { synchronized (stateLock) { return localAddress; } @@ -605,9 +712,11 @@ public String toString() { sb.append("closed"); } else { synchronized (stateLock) { - InetSocketAddress addr = localAddress; + SocketAddress addr = localAddress; if (addr == null) { sb.append("unbound"); + } else if (isUnixSocket()) { + sb.append(UnixDomainSockets.getRevealedLocalAddressAsString(addr)); } else { sb.append(Net.getRevealedLocalAddressAsString(addr)); } diff --git a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java index 6e53efc6744..f5ce85fc5c6 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,14 @@ static Socket create(SocketChannelImpl sc) { } } + private InetSocketAddress localAddress() { + return (InetSocketAddress) sc.localAddress(); + } + + private InetSocketAddress remoteAddress() { + return (InetSocketAddress) sc.remoteAddress(); + } + @Override public void connect(SocketAddress remote) throws IOException { connect(remote, 0); @@ -106,7 +114,7 @@ public void bind(SocketAddress local) throws IOException { @Override public InetAddress getInetAddress() { - InetSocketAddress remote = sc.remoteAddress(); + InetSocketAddress remote = remoteAddress(); if (remote == null) { return null; } else { @@ -117,7 +125,7 @@ public InetAddress getInetAddress() { @Override public InetAddress getLocalAddress() { if (sc.isOpen()) { - InetSocketAddress local = sc.localAddress(); + InetSocketAddress local = localAddress(); if (local != null) { return Net.getRevealedLocalAddress(local).getAddress(); } @@ -127,7 +135,7 @@ public InetAddress getLocalAddress() { @Override public int getPort() { - InetSocketAddress remote = sc.remoteAddress(); + InetSocketAddress remote = remoteAddress(); if (remote == null) { return 0; } else { @@ -137,7 +145,7 @@ public int getPort() { @Override public int getLocalPort() { - InetSocketAddress local = sc.localAddress(); + InetSocketAddress local = localAddress(); if (local == null) { return -1; } else { @@ -152,12 +160,7 @@ public SocketAddress getRemoteSocketAddress() { @Override public SocketAddress getLocalSocketAddress() { - InetSocketAddress local = sc.localAddress(); - if (local != null) { - return Net.getRevealedLocalAddress(local); - } else { - return null; - } + return Net.getRevealedLocalAddress(sc.localAddress()); } @Override diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 43a50f5c0d6..bb5669c0377 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -36,7 +36,6 @@ import java.net.SocketException; import java.net.SocketOption; import java.net.SocketTimeoutException; -import java.net.StandardProtocolFamily; import java.net.StandardSocketOptions; import java.nio.ByteBuffer; import java.nio.channels.AlreadyBoundException; @@ -50,11 +49,15 @@ import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; +import java.nio.file.Path; import java.util.Collections; import java.util.HashSet; -import java.util.Objects; import java.util.Set; +import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; +import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.INET6; +import static java.net.StandardProtocolFamily.UNIX; import sun.net.ConnectionResetException; import sun.net.NetHooks; @@ -114,52 +117,35 @@ class SocketChannelImpl private long writerThread; // Binding - private InetSocketAddress localAddress; - private InetSocketAddress remoteAddress; + private SocketAddress localAddress; + private SocketAddress remoteAddress; // Socket adaptor, created on demand private Socket socket; // -- End of fields protected by stateLock - // Constructor for normal connecting sockets - // SocketChannelImpl(SelectorProvider sp) throws IOException { - this(sp, Net.isIPv6Available() - ? StandardProtocolFamily.INET6 - : StandardProtocolFamily.INET); + this(sp, Net.isIPv6Available() ? INET6 : INET); } SocketChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException { super(sp); Objects.requireNonNull(family, "'family' is null"); - if ((family != StandardProtocolFamily.INET) && - (family != StandardProtocolFamily.INET6)) { + if ((family != INET) && (family != INET6) && (family != UNIX)) { throw new UnsupportedOperationException("Protocol family not supported"); } - if (family == StandardProtocolFamily.INET6 && !Net.isIPv6Available()) { + if (family == INET6 && !Net.isIPv6Available()) { throw new UnsupportedOperationException("IPv6 not available"); } - this.family = family; - this.fd = Net.socket(family, true); - this.fdVal = IOUtil.fdVal(fd); - } - SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) - throws IOException - { - super(sp); - this.family = Net.isIPv6Available() - ? StandardProtocolFamily.INET6 - : StandardProtocolFamily.INET; - this.fd = fd; - this.fdVal = IOUtil.fdVal(fd); - - if (bound) { - synchronized (stateLock) { - this.localAddress = Net.localAddress(fd); - } + this.family = family; + if (family == UNIX) { + this.fd = UnixDomainSockets.socket(); + } else { + this.fd = Net.socket(family, true); } + this.fdVal = IOUtil.fdVal(fd); } // Constructor for sockets obtained from server sockets @@ -167,7 +153,7 @@ class SocketChannelImpl SocketChannelImpl(SelectorProvider sp, ProtocolFamily family, FileDescriptor fd, - InetSocketAddress isa) + SocketAddress remoteAddress) throws IOException { super(sp); @@ -175,12 +161,30 @@ class SocketChannelImpl this.fd = fd; this.fdVal = IOUtil.fdVal(fd); synchronized (stateLock) { - this.localAddress = Net.localAddress(fd); - this.remoteAddress = isa; + if (family == UNIX) { + this.localAddress = UnixDomainSockets.localAddress(fd); + } else { + this.localAddress = Net.localAddress(fd); + } + this.remoteAddress = remoteAddress; this.state = ST_CONNECTED; } } + /** + * Returns true if this channel is to a INET or INET6 socket. + */ + boolean isNetSocket() { + return (family == INET) || (family == INET6); + } + + /** + * Returns true if this channel is to a UNIX socket. + */ + boolean isUnixSocket() { + return (family == UNIX); + } + /** * Checks that the channel is open. * @@ -215,8 +219,13 @@ private void ensureOpenAndConnected() throws ClosedChannelException { @Override public Socket socket() { synchronized (stateLock) { - if (socket == null) - socket = SocketAdaptor.create(this); + if (socket == null) { + if (isNetSocket()) { + socket = SocketAdaptor.create(this); + } else { + throw new UnsupportedOperationException("Not supported"); + } + } return socket; } } @@ -225,7 +234,11 @@ public Socket socket() { public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { ensureOpen(); - return Net.getRevealedLocalAddress(localAddress); + if (isUnixSocket()) { + return UnixDomainSockets.getRevealedLocalAddress(localAddress); + } else { + return Net.getRevealedLocalAddress(localAddress); + } } } @@ -250,15 +263,17 @@ public SocketChannel setOption(SocketOption name, T value) synchronized (stateLock) { ensureOpen(); - if (name == StandardSocketOptions.IP_TOS) { - Net.setSocketOption(fd, family, name, value); - return this; - } - - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { - // SO_REUSEADDR emulated when using exclusive bind - isReuseAddress = (Boolean)value; - return this; + if (isNetSocket()) { + if (name == StandardSocketOptions.IP_TOS) { + // special handling for IP_TOS + Net.setSocketOption(fd, family, name, value); + return this; + } + if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { + // SO_REUSEADDR emulated when using exclusive bind + isReuseAddress = (Boolean) value; + return this; + } } // no options that require special handling @@ -279,14 +294,15 @@ public T getOption(SocketOption name) synchronized (stateLock) { ensureOpen(); - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { - // SO_REUSEADDR emulated when using exclusive bind - return (T)Boolean.valueOf(isReuseAddress); - } - - // special handling for IP_TOS - if (name == StandardSocketOptions.IP_TOS) { - return (T) Net.getSocketOption(fd, family, name); + if (isNetSocket()) { + if (name == StandardSocketOptions.IP_TOS) { + // special handling for IP_TOS + return (T) Net.getSocketOption(fd, family, name); + } + if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { + // SO_REUSEADDR emulated when using exclusive bind + return (T) Boolean.valueOf(isReuseAddress); + } } // no options that require special handling @@ -295,9 +311,10 @@ public T getOption(SocketOption name) } private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); + static final Set> defaultInetOptions = defaultInetOptions(); + static final Set> defaultUnixOptions = defaultUnixOptions(); - private static Set> defaultOptions() { + private static Set> defaultInetOptions() { HashSet> set = new HashSet<>(); set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); @@ -314,11 +331,24 @@ private static Set> defaultOptions() { set.addAll(ExtendedSocketOptions.clientSocketOptions()); return Collections.unmodifiableSet(set); } + + private static Set> defaultUnixOptions() { + HashSet> set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_LINGER); + set.addAll(ExtendedSocketOptions.unixDomainSocketOptions()); + return Collections.unmodifiableSet(set); + } } @Override public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; + if (isUnixSocket()) { + return DefaultOptionsHolder.defaultUnixOptions; + } else { + return DefaultOptionsHolder.defaultInetOptions; + } } /** @@ -625,7 +655,7 @@ private boolean tryLockedConfigureBlocking(boolean block) throws IOException { /** * Returns the local address, or null if not bound */ - InetSocketAddress localAddress() { + SocketAddress localAddress() { synchronized (stateLock) { return localAddress; } @@ -634,7 +664,7 @@ InetSocketAddress localAddress() { /** * Returns the remote address, or null if not connected */ - InetSocketAddress remoteAddress() { + SocketAddress remoteAddress() { synchronized (stateLock) { return remoteAddress; } @@ -652,19 +682,11 @@ public SocketChannel bind(SocketAddress local) throws IOException { throw new ConnectionPendingException(); if (localAddress != null) throw new AlreadyBoundException(); - InetSocketAddress isa; - if (local == null) { - isa = new InetSocketAddress(Net.anyLocalAddress(family), 0); + if (isUnixSocket()) { + localAddress = unixBind(local); } else { - isa = Net.checkAddress(local, family); - } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkListen(isa.getPort()); + localAddress = netBind(local); } - NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); - Net.bind(family, fd, isa.getAddress(), isa.getPort()); - localAddress = Net.localAddress(fd); } } finally { writeLock.unlock(); @@ -675,6 +697,38 @@ public SocketChannel bind(SocketAddress local) throws IOException { return this; } + private SocketAddress unixBind(SocketAddress local) throws IOException { + UnixDomainSockets.checkPermission(); + if (local == null) { + return UnixDomainSockets.UNNAMED; + } else { + Path path = UnixDomainSockets.checkAddress(local).getPath(); + if (path.toString().isEmpty()) { + return UnixDomainSockets.UNNAMED; + } else { + // bind to non-empty path + UnixDomainSockets.bind(fd, path); + return UnixDomainSockets.localAddress(fd); + } + } + } + + private SocketAddress netBind(SocketAddress local) throws IOException { + InetSocketAddress isa; + if (local == null) { + isa = new InetSocketAddress(Net.anyLocalAddress(family), 0); + } else { + isa = Net.checkAddress(local, family); + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkListen(isa.getPort()); + } + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); + Net.bind(family, fd, isa.getAddress(), isa.getPort()); + return Net.localAddress(fd); + } + @Override public boolean isConnected() { return (state == ST_CONNECTED); @@ -694,7 +748,7 @@ public boolean isConnectionPending() { * @throws ConnectionPendingException is a connection is pending * @throws IOException if the pre-connect hook fails */ - private void beginConnect(boolean blocking, InetSocketAddress isa) + private void beginConnect(boolean blocking, SocketAddress sa) throws IOException { if (blocking) { @@ -711,9 +765,11 @@ private void beginConnect(boolean blocking, InetSocketAddress isa) assert state == ST_UNCONNECTED; this.state = ST_CONNECTIONPENDING; - if (localAddress == null) + if (isNetSocket() && (localAddress == null)) { + InetSocketAddress isa = (InetSocketAddress) sa; NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort()); - remoteAddress = isa; + } + remoteAddress = sa; if (blocking) { // record thread so it can be signalled if needed @@ -737,7 +793,11 @@ private void endConnect(boolean blocking, boolean completed) if (completed) { synchronized (stateLock) { if (state == ST_CONNECTIONPENDING) { - localAddress = Net.localAddress(fd); + if (isUnixSocket()) { + localAddress = UnixDomainSockets.localAddress(fd); + } else { + localAddress = Net.localAddress(fd); + } state = ST_CONNECTED; } } @@ -747,29 +807,34 @@ private void endConnect(boolean blocking, boolean completed) /** * Checks the remote address to which this channel is to be connected. */ - private InetSocketAddress checkRemote(SocketAddress sa) { - InetSocketAddress isa = Net.checkAddress(sa, family); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - } - InetAddress address = isa.getAddress(); - if (address.isAnyLocalAddress()) { - int port = isa.getPort(); - if (address instanceof Inet4Address) { - return new InetSocketAddress(Net.inet4LoopbackAddress(), port); + private SocketAddress checkRemote(SocketAddress sa) { + if (isUnixSocket()) { + UnixDomainSockets.checkPermission(); + return UnixDomainSockets.checkAddress(sa); + } else { + InetSocketAddress isa = Net.checkAddress(sa, family); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); + } + InetAddress address = isa.getAddress(); + if (address.isAnyLocalAddress()) { + int port = isa.getPort(); + if (address instanceof Inet4Address) { + return new InetSocketAddress(Net.inet4LoopbackAddress(), port); + } else { + assert family == INET6; + return new InetSocketAddress(Net.inet6LoopbackAddress(), port); + } } else { - assert family == StandardProtocolFamily.INET6; - return new InetSocketAddress(Net.inet6LoopbackAddress(), port); + return isa; } - } else { - return isa; } } @Override public boolean connect(SocketAddress remote) throws IOException { - InetSocketAddress isa = checkRemote(remote); + SocketAddress sa = checkRemote(remote); try { readLock.lock(); try { @@ -778,11 +843,13 @@ public boolean connect(SocketAddress remote) throws IOException { boolean blocking = isBlocking(); boolean connected = false; try { - beginConnect(blocking, isa); - int n = Net.connect(family, - fd, - isa.getAddress(), - isa.getPort()); + beginConnect(blocking, sa); + int n; + if (isUnixSocket()) { + n = UnixDomainSockets.connect(fd, sa); + } else { + n = Net.connect(family, fd, sa); + } if (n > 0) { connected = true; } else if (blocking) { @@ -807,7 +874,7 @@ public boolean connect(SocketAddress remote) throws IOException { } catch (IOException ioe) { // connect failed, close the channel close(); - throw SocketExceptions.of(ioe, isa); + throw SocketExceptions.of(ioe, sa); } } @@ -848,7 +915,11 @@ private void endFinishConnect(boolean blocking, boolean completed) if (completed) { synchronized (stateLock) { if (state == ST_CONNECTIONPENDING) { - localAddress = Net.localAddress(fd); + if (isUnixSocket()) { + localAddress = UnixDomainSockets.localAddress(fd); + } else { + localAddress = Net.localAddress(fd); + } state = ST_CONNECTED; } } @@ -1087,7 +1158,7 @@ private boolean finishTimedConnect(long nanos) throws IOException { * @throws SocketTimeoutException if the read timeout elapses */ void blockingConnect(SocketAddress remote, long nanos) throws IOException { - InetSocketAddress isa = checkRemote(remote); + SocketAddress sa = checkRemote(remote); try { readLock.lock(); try { @@ -1097,11 +1168,16 @@ void blockingConnect(SocketAddress remote, long nanos) throws IOException { throw new IllegalBlockingModeException(); boolean connected = false; try { - beginConnect(true, isa); + beginConnect(true, sa); // change socket to non-blocking lockedConfigureBlocking(false); try { - int n = Net.connect(fd, isa.getAddress(), isa.getPort()); + int n; + if (isUnixSocket()) { + n = UnixDomainSockets.connect(fd, sa); + } else { + n = Net.connect(family, fd, sa); + } connected = (n > 0) ? true : finishTimedConnect(nanos); } finally { // restore socket to blocking mode (if channel is open) @@ -1119,7 +1195,7 @@ void blockingConnect(SocketAddress remote, long nanos) throws IOException { } catch (IOException ioe) { // connect failed, close the channel close(); - throw SocketExceptions.of(ioe, isa); + throw SocketExceptions.of(ioe, sa); } } @@ -1390,10 +1466,14 @@ public String toString() { sb.append(" oshut"); break; } - InetSocketAddress addr = localAddress(); + SocketAddress addr = localAddress(); if (addr != null) { sb.append(" local="); - sb.append(Net.getRevealedLocalAddressAsString(addr)); + if (isUnixSocket()) { + sb.append(UnixDomainSockets.getRevealedLocalAddressAsString(addr)); + } else { + sb.append(Net.getRevealedLocalAddressAsString(addr)); + } } if (remoteAddress() != null) { sb.append(" remote="); diff --git a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java new file mode 100644 index 00000000000..634f5694605 --- /dev/null +++ b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.ch; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.BindException; +import java.net.NetPermission; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.UnsupportedAddressTypeException; +import java.nio.file.FileSystems; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.spi.FileSystemProvider; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import sun.nio.fs.AbstractFileSystemProvider; + +class UnixDomainSockets { + private UnixDomainSockets() { } + + static final UnixDomainSocketAddress UNNAMED = UnixDomainSocketAddress.of(""); + + private static final boolean supported; + + private static final String tempDir = UnixDomainSocketsUtil.getTempDir(); + + private static final NetPermission accessUnixDomainSocket = + new NetPermission("accessUnixDomainSocket"); + + static boolean isSupported() { + return supported; + } + + static void checkPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(accessUnixDomainSocket); + } + + static UnixDomainSocketAddress getRevealedLocalAddress(SocketAddress sa) { + UnixDomainSocketAddress addr = (UnixDomainSocketAddress) sa; + try { + checkPermission(); + // Security check passed + } catch (SecurityException e) { + // Return unnamed address only if security check fails + addr = UNNAMED; + } + return addr; + } + + static UnixDomainSocketAddress localAddress(FileDescriptor fd) throws IOException { + String path = new String(localAddress0(fd), UnixDomainSocketsUtil.getCharset()); + return UnixDomainSocketAddress.of(path); + } + + private static native byte[] localAddress0(FileDescriptor fd) throws IOException; + + static String getRevealedLocalAddressAsString(SocketAddress sa) { + return (System.getSecurityManager() != null) ? sa.toString() : ""; + } + + static UnixDomainSocketAddress checkAddress(SocketAddress sa) { + if (sa == null) + throw new NullPointerException(); + if (!(sa instanceof UnixDomainSocketAddress)) + throw new UnsupportedAddressTypeException(); + return (UnixDomainSocketAddress) sa; + } + + static byte[] getPathBytes(Path path) { + FileSystemProvider provider = FileSystems.getDefault().provider(); + return ((AbstractFileSystemProvider) provider).getSunPathForSocketFile(path); + } + + static FileDescriptor socket() throws IOException { + return IOUtil.newFD(socket0()); + } + + static void bind(FileDescriptor fd, Path addr) throws IOException { + byte[] path = getPathBytes(addr); + bind0(fd, path); + } + + private static Random getRandom() { + try { + return SecureRandom.getInstance("NativePRNGNonBlocking"); + } catch (NoSuchAlgorithmException e) { + return new SecureRandom(); // This should not fail + } + } + + private static final Random random = getRandom(); + + /** + * Return a possible temporary name to bind to, which is different for each call + * Name is of the form /socket_ + */ + static UnixDomainSocketAddress generateTempName() throws IOException { + String dir = UnixDomainSockets.tempDir; + if (dir == null) + throw new BindException("Could not locate temporary directory for sockets"); + int rnd = random.nextInt(Integer.MAX_VALUE); + try { + Path path = Path.of(dir, "socket_" + rnd); + return UnixDomainSocketAddress.of(path); + } catch (InvalidPathException e) { + throw new BindException("Invalid temporary directory"); + } + } + + static int connect(FileDescriptor fd, SocketAddress sa) throws IOException { + return UnixDomainSockets.connect(fd, ((UnixDomainSocketAddress) sa).getPath()); + } + + static int connect(FileDescriptor fd, Path path) throws IOException { + return connect0(fd, getPathBytes(path)); + } + + static int accept(FileDescriptor fd, FileDescriptor newfd, String[] paths) + throws IOException + { + Object[] array = new Object[1]; + int n = accept0(fd, newfd, array); + if (n > 0) { + byte[] bytes = (byte[]) array[0]; + paths[0] = new String(bytes, UnixDomainSocketsUtil.getCharset()); + } + return n; + } + + private static native boolean socketSupported(); + + private static native int socket0() throws IOException; + + private static native void bind0(FileDescriptor fd, byte[] path) + throws IOException; + + private static native int connect0(FileDescriptor fd, byte[] path) + throws IOException; + + private static native int accept0(FileDescriptor fd, FileDescriptor newfd, Object[] array) + throws IOException; + + static { + // Load all required native libs + IOUtil.load(); + supported = socketSupported(); + } +} diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java b/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java index 679f5857132..b100d3a64a4 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,4 +154,10 @@ public boolean exists(Path file) { return false; } } + + /** + * Returns a path name as bytes for a Unix domain socket. + * Different encodings may be used for these names on some platforms. + */ + public abstract byte[] getSunPathForSocketFile(Path file); } diff --git a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java index 6fc8ad93384..bcd0761dfa6 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java +++ b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java @@ -92,16 +92,8 @@ public static enum TypeAnnotationTarget { METHOD_FORMAL_PARAMETER, THROWS, /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This enum constant is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) RECORD_COMPONENT; } diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index bbdbf5a4713..cdb24121722 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -354,7 +354,7 @@ public enum KnownOIDs { ECDH("1.3.132.1.12"), // OIW secsig 1.3.14.3.* - OIW_DES_CBC("1.3.14.3.2.7", "DES/CBC"), + OIW_DES_CBC("1.3.14.3.2.7", "DES/CBC", "DES"), OIW_DSA("1.3.14.3.2.12", "DSA") { @Override @@ -371,6 +371,8 @@ public enum KnownOIDs { boolean registerNames() { return false; } }, + DESede("1.3.14.3.2.17", "DESede"), + SHA_1("1.3.14.3.2.26", "SHA-1", "SHA", "SHA1"), OIW_SHA1withDSA("1.3.14.3.2.27", "SHA1withDSA") { diff --git a/src/java.base/share/classes/sun/util/resources/LocaleNames.properties b/src/java.base/share/classes/sun/util/resources/LocaleNames.properties index 459241331f4..bc48b2870f3 100644 --- a/src/java.base/share/classes/sun/util/resources/LocaleNames.properties +++ b/src/java.base/share/classes/sun/util/resources/LocaleNames.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ bg=Bulgarian bh=Bihari bi=Bislama bm=Bambara -bn=Bengali +bn=Bangla bo=Tibetan br=Breton bs=Bosnian @@ -87,10 +87,10 @@ fi=Finnish fj=Fijian fo=Faroese fr=French -fy=Frisian +fy=Western Frisian ga=Irish gd=Scottish Gaelic -gl=Gallegan +gl=Galician gn=Guarani gu=Gujarati gv=Manx @@ -99,7 +99,7 @@ he=Hebrew hi=Hindi ho=Hiri Motu hr=Croatian -ht=Haitian +ht=Haitian Creole hu=Hungarian hy=Armenian hz=Herero @@ -121,9 +121,9 @@ jv=Javanese ka=Georgian kg=Kongo ki=Kikuyu -kj=Kwanyama +kj=Kuanyama kk=Kazakh -kl=Greenlandic +kl=Kalaallisut km=Khmer kn=Kannada ko=Korean @@ -132,7 +132,7 @@ ks=Kashmiri ku=Kurdish kv=Komi kw=Cornish -ky=Kirghiz +ky=Kyrgyz la=Latin lb=Luxembourgish lg=Ganda @@ -167,15 +167,15 @@ ny=Nyanja oc=Occitan oj=Ojibwa om=Oromo -or=Oriya -os=Ossetian -pa=Panjabi +or=Odia +os=Ossetic +pa=Punjabi pi=Pali pl=Polish -ps=Pushto +ps=Pashto pt=Portuguese qu=Quechua -rm=Raeto-Romance +rm=Romansh rn=Rundi ro=Romanian ru=Russian @@ -185,7 +185,7 @@ sc=Sardinian sd=Sindhi se=Northern Sami sg=Sango -si=Sinhalese +si=Sinhala sk=Slovak sl=Slovenian sm=Samoan @@ -206,13 +206,13 @@ ti=Tigrinya tk=Turkmen tl=Tagalog tn=Tswana -to=Tonga +to=Tongan tr=Turkish ts=Tsonga tt=Tatar tw=Twi ty=Tahitian -ug=Uighur +ug=Uyghur uk=Ukrainian ur=Urdu uz=Uzbek @@ -246,14 +246,14 @@ ale=Aleut alg=Algonquian alt=Southern Altai amh=Amharic -ang=English, Old (ca.450-1100) +ang=Old English anp=Angika apa=Apache ara=Arabic -arc=Official Aramaic (700-300 BCE) +arc=Aramaic arg=Aragonese arm=Armenian -arn=Mapudungun +arn=Mapuche arp=Arapaho art=Artificial arw=Arawak @@ -273,7 +273,7 @@ bal=Baluchi bam=Bambara ban=Balinese baq=Basque -bas=Basa +bas=Basaa bat=Baltic bej=Beja bel=Belarusian @@ -298,7 +298,7 @@ bur=Burmese byn=Blin cad=Caddo cai=Central American Indian -car=Galibi Carib +car=Carib cat=Catalan cau=Caucasian ceb=Cebuano @@ -310,7 +310,7 @@ chg=Chagatai chi=Chinese chk=Chuukese chm=Mari -chn=Chinook jargon +chn=Chinook Jargon cho=Choctaw chp=Chipewyan chr=Cherokee @@ -325,7 +325,7 @@ cpe=Creoles and pidgins, English based cpf=Creoles and pidgins, French-based cpp=Creoles and pidgins, Portuguese-based cre=Cree -crh=Crimean Tatar +crh=Crimean Turkish crp=Creoles and pidgins csb=Kashubian cus=Cushitic @@ -335,7 +335,7 @@ dan=Danish dar=Dargwa day=Land Dayak del=Delaware -den=Slave (Athapascan) +den=Slave dgr=Dogrib din=Dinka div=Divehi @@ -343,16 +343,16 @@ doi=Dogri dra=Dravidian dsb=Lower Sorbian dua=Duala -dum=Dutch, Middle (ca.1050-1350) +dum=Middle Dutch dut=Dutch dyu=Dyula dzo=Dzongkha efi=Efik -egy=Egyptian (Ancient) +egy=Ancient Egyptian eka=Ekajuk elx=Elamite eng=English -enm=English, Middle (1100-1500) +enm=Middle English epo=Esperanto est=Estonian ewe=Ewe @@ -366,8 +366,8 @@ fin=Finnish fiu=Finno-Ugrian fon=Fon fre=French -frm=French, Middle (ca.1400-1600) -fro=French, Old (842-ca.1400) +frm=Middle French +fro=Old French frr=Northern Frisian frs=Eastern Frisian fry=Western Frisian @@ -385,18 +385,18 @@ gla=Gaelic gle=Irish glg=Galician glv=Manx -gmh=German, Middle High (ca.1050-1500) -goh=German, Old High (ca.750-1050) +gmh=Middle High German +goh=Old High German gon=Gondi gor=Gorontalo got=Gothic grb=Grebo -grc=Greek, Ancient (to 1453) +grc=Ancient Greek gre=Greek, Modern (1453-) grn=Guarani gsw=Swiss German guj=Gujarati -gwi=Gwich'in +gwi=Gwich\u02bcin hai=Haida hat=Haitian hau=Hausa @@ -488,8 +488,8 @@ lub=Luba-Katanga lug=Ganda lui=Luiseno lun=Lunda -luo=Luo (Kenya and Tanzania) -lus=Lushai +luo=Luo +lus=Mizo mac=Macedonian mad=Madurese mag=Magahi @@ -506,7 +506,7 @@ may=Malay mdf=Moksha mdr=Mandar men=Mende -mga=Irish, Middle (900-1200) +mga=Middle Irish mic=Mi'kmaq min=Minangkabau mis=Uncoded @@ -519,9 +519,9 @@ mno=Manobo moh=Mohawk mon=Mongolian mos=Mossi -mul=Multiple +mul=Multiple languages mun=Munda -mus=Creek +mus=Muscogee mwl=Mirandese mwr=Marwari myn=Mayan @@ -536,17 +536,17 @@ nde=Ndebele, North ndo=Ndonga nds=Low German nep=Nepali -new=Nepal Bhasa +new=Newari nia=Nias nic=Niger-Kordofanian niu=Niuean nno=Norwegian Nynorsk nob=Bokm\u00e5l, Norwegian nog=Nogai -non=Norse, Old +non=Old Norse nor=Norwegian -nqo=N'Ko -nso=Pedi +nqo=N\u2019Ko +nso=Northern Sotho nub=Nubian nwc=Classical Newari nya=Chichewa @@ -560,7 +560,7 @@ ori=Oriya orm=Oromo osa=Osage oss=Ossetian -ota=Turkish, Ottoman (1500-1928) +ota=Ottoman Turkish oto=Otomian paa=Papuan pag=Pangasinan @@ -569,7 +569,7 @@ pam=Pampanga pan=Panjabi pap=Papiamento pau=Palauan -peo=Persian, Old (ca.600-400 B.C.) +peo=Old Persian per=Persian phi=Philippine phn=Phoenician @@ -578,7 +578,7 @@ pol=Polish pon=Pohnpeian por=Portuguese pra=Prakrit -pro=Proven\u00e7al, Old (to 1500) +pro=Old Proven\u00e7al pus=Pushto; Pashto que=Quechua raj=Rajasthani @@ -593,7 +593,7 @@ rup=Aromanian rus=Russian sad=Sandawe sag=Sango -sah=Yakut +sah=Sakha sai=South American Indian sal=Salishan sam=Samaritan Aramaic @@ -604,7 +604,7 @@ scn=Sicilian sco=Scots sel=Selkup sem=Semitic -sga=Irish, Old (to 900) +sga=Old Irish sgn=Sign shn=Shan sid=Sidamo @@ -624,7 +624,7 @@ sms=Skolt Sami sna=Shona snd=Sindhi snk=Soninke -sog=Sogdian +sog=Sogdien som=Somali son=Songhai sot=Sotho, Southern @@ -662,7 +662,7 @@ tkl=Tokelau tlh=Klingon tli=Tlingit tmh=Tamashek -tog=Tonga (Nyasa) +tog=Nyasa Tonga ton=Tonga (Tonga Islands) tpi=Tok Pisin tsi=Tsimshian @@ -681,7 +681,7 @@ uga=Ugaritic uig=Uighur ukr=Ukrainian umb=Umbundu -und=Undetermined +und=Unknown language urd=Urdu uzb=Uzbek vai=Vai @@ -690,7 +690,7 @@ vie=Vietnamese vol=Volap\u00fck vot=Votic wak=Wakashan -wal=Wolaitta +wal=Wolaytta war=Waray was=Washo wel=Welsh @@ -725,7 +725,7 @@ Bali=Balinese Bamu=Bamum Bass=Bassa Vah Batk=Batak -Beng=Bengali +Beng=Bangla Blis=Blissymbols Bopo=Bopomofo Brah=Brahmi @@ -750,7 +750,7 @@ Egyh=Egyptian hieratic Egyp=Egyptian hieroglyphs Elba=Elbasan Ethi=Ethiopic -Geok=Khutsuri +Geok=Georgian Khutsuri Geor=Georgian Glag=Glagolitic Goth=Gothic @@ -761,12 +761,12 @@ Guru=Gurmukhi Hang=Hangul Hani=Han Hano=Hanunoo -Hans=Simplified Han -Hant=Traditional Han +Hans=Simplified +Hant=Traditional Hebr=Hebrew Hira=Hiragana Hmng=Pahawh Hmong -Hrkt=Katakana or Hiragana +Hrkt=Japanese syllabaries Hung=Old Hungarian Inds=Indus Ital=Old Italic @@ -780,7 +780,7 @@ Knda=Kannada Kore=Korean Kpel=Kpelle Kthi=Kaithi -Lana=Tai Tham +Lana=Lanna Laoo=Lao Latf=Fraktur Latin Latg=Gaelic Latin @@ -789,11 +789,11 @@ Lepc=Lepcha Limb=Limbu Lina=Linear A Linb=Linear B -Lisu=Lisu +Lisu=Fraser Loma=Loma Lyci=Lycian Lydi=Lydian -Mand=Mandaic +Mand=Mandaean Mani=Manichaean Maya=Mayan hieroglyphs Mend=Mende @@ -806,12 +806,12 @@ Mtei=Meitei Mayek Mymr=Myanmar Narb=Old North Arabian Nbat=Nabataean -Nkgb=Nakhi Geba +Nkgb=Naxi Geba Nkoo=N\u2019Ko Ogam=Ogham Olck=Ol Chiki Orkh=Orkhon -Orya=Oriya +Orya=Odia Osma=Osmanya Palm=Palmyrene Perm=Old Permic @@ -820,7 +820,7 @@ Phli=Inscriptional Pahlavi Phlp=Psalter Pahlavi Phlv=Book Pahlavi Phnx=Phoenician -Plrd=Miao +Plrd=Pollard Phonetic Prti=Inscriptional Parthian Rjng=Rejang Roro=Rongorongo @@ -831,7 +831,7 @@ Sarb=Old South Arabian Saur=Saurashtra Sgnw=SignWriting Shaw=Shavian -Sind=Sindhi +Sind=Khudawadi Sinh=Sinhala Sund=Sundanese Sylo=Syloti Nagri @@ -854,16 +854,16 @@ Tibt=Tibetan Ugar=Ugaritic Vaii=Vai Visp=Visible Speech -Wara=Warang Citi +Wara=Varang Kshiti Xpeo=Old Persian Xsux=Sumero-Akkadian Cuneiform Yiii=Yi -Zinh=Inherited script +Zinh=Inherited Zmth=Mathematical Notation Zsym=Symbols Zxxx=Unwritten -Zyyy=Undetermined script -Zzzz=Uncoded script +Zyyy=Common +Zzzz=Unknown Script # country names # key is ISO 3166 country code @@ -871,7 +871,7 @@ Zzzz=Uncoded script AD=Andorra AE=United Arab Emirates AF=Afghanistan -AG=Antigua and Barbuda +AG=Antigua & Barbuda AI=Anguilla AL=Albania AM=Armenia @@ -885,7 +885,7 @@ AU=Australia AW=Aruba AX=\u00c5land Islands AZ=Azerbaijan -BA=Bosnia and Herzegovina +BA=Bosnia & Herzegovina BB=Barbados BD=Bangladesh BE=Belgium @@ -894,11 +894,11 @@ BG=Bulgaria BH=Bahrain BI=Burundi BJ=Benin -BL=Saint Barth\u00e9lemy +BL=St. Barth\u00e9lemy BM=Bermuda BN=Brunei BO=Bolivia -BQ=Bonaire, Sint Eustatius and Saba +BQ=Caribbean Netherlands BR=Brazil BS=Bahamas BT=Bhutan @@ -907,12 +907,12 @@ BW=Botswana BY=Belarus BZ=Belize CA=Canada -CC=Cocos Islands -CD=The Democratic Republic Of Congo +CC=Cocos (Keeling) Islands +CD=Congo - Kinshasa CF=Central African Republic -CG=Congo +CG=Congo - Brazzaville CH=Switzerland -CI=C\u00F4te d'Ivoire +CI=C\u00f4te d\u2019Ivoire CK=Cook Islands CL=Chile CM=Cameroon @@ -925,7 +925,7 @@ CV=Cape Verde CW=Cura\u00e7ao CX=Christmas Island CY=Cyprus -CZ=Czech Republic +CZ=Czechia DE=Germany DJ=Djibouti DK=Denmark @@ -959,13 +959,13 @@ GN=Guinea GP=Guadeloupe GQ=Equatorial Guinea GR=Greece -GS=South Georgia And The South Sandwich Islands +GS=South Georgia & South Sandwich Islands GT=Guatemala GU=Guam GW=Guinea-Bissau GY=Guyana -HK=Hong Kong -HM=Heard Island And McDonald Islands +HK=Hong Kong SAR China +HM=Heard & McDonald Islands HN=Honduras HR=Croatia HT=Haiti @@ -973,7 +973,7 @@ HU=Hungary ID=Indonesia IE=Ireland IL=Israel -IM=Isle Of Man +IM=Isle of Man IN=India IO=British Indian Ocean Territory IQ=Iraq @@ -989,7 +989,7 @@ KG=Kyrgyzstan KH=Cambodia KI=Kiribati KM=Comoros -KN=Saint Kitts And Nevis +KN=St. Kitts & Nevis KP=North Korea KR=South Korea KW=Kuwait @@ -997,7 +997,7 @@ KY=Cayman Islands KZ=Kazakhstan LA=Laos LB=Lebanon -LC=Saint Lucia +LC=St. Lucia LI=Liechtenstein LK=Sri Lanka LR=Liberia @@ -1010,14 +1010,14 @@ MA=Morocco MC=Monaco MD=Moldova ME=Montenegro -MF=Saint Martin +MF=St. Martin MG=Madagascar MH=Marshall Islands -MK=Macedonia +MK=North Macedonia ML=Mali -MM=Myanmar +MM=Myanmar (Burma) MN=Mongolia -MO=Macao +MO=Macao SAR China MP=Northern Mariana Islands MQ=Martinique MR=Mauritania @@ -1049,15 +1049,15 @@ PG=Papua New Guinea PH=Philippines PK=Pakistan PL=Poland -PM=Saint Pierre And Miquelon -PN=Pitcairn +PM=St. Pierre & Miquelon +PN=Pitcairn Islands PR=Puerto Rico -PS=Palestine +PS=Palestinian Territories PT=Portugal PW=Palau PY=Paraguay QA=Qatar -RE=Reunion +RE=R\u00e9union RO=Romania RS=Serbia RU=Russia @@ -1068,9 +1068,9 @@ SC=Seychelles SD=Sudan SE=Sweden SG=Singapore -SH=Saint Helena +SH=St. Helena SI=Slovenia -SJ=Svalbard And Jan Mayen +SJ=Svalbard & Jan Mayen SK=Slovakia SL=Sierra Leone SM=San Marino @@ -1078,12 +1078,12 @@ SN=Senegal SO=Somalia SR=Suriname SS=South Sudan -ST=Sao Tome And Principe +ST=S\u00e3o Tom\u00e9 & Pr\u00edncipe SV=El Salvador -SX=Sint Maarten (Dutch part) +SX=Sint Maarten SY=Syria -SZ=Swaziland -TC=Turks And Caicos Islands +SZ=Eswatini +TC=Turks & Caicos Islands TD=Chad TF=French Southern Territories TG=Togo @@ -1095,24 +1095,24 @@ TM=Turkmenistan TN=Tunisia TO=Tonga TR=Turkey -TT=Trinidad and Tobago +TT=Trinidad & Tobago TV=Tuvalu TW=Taiwan TZ=Tanzania UA=Ukraine UG=Uganda -UM=United States Minor Outlying Islands +UM=U.S. Outlying Islands US=United States UY=Uruguay UZ=Uzbekistan -VA=Vatican -VC=Saint Vincent And The Grenadines +VA=Vatican City +VC=St. Vincent & Grenadines VE=Venezuela VG=British Virgin Islands VI=U.S. Virgin Islands VN=Vietnam VU=Vanuatu -WF=Wallis And Futuna +WF=Wallis & Futuna WS=Samoa YE=Yemen YT=Mayotte @@ -1139,9 +1139,9 @@ ZW=Zimbabwe 029=Caribbean 030=Eastern Asia 034=Southern Asia -035=South-Eastern Asia +035=Southeast Asia 039=Southern Europe -053=Australia and New Zealand +053=Australasia 054=Melanesia 057=Micronesian Region 061=Polynesia @@ -1152,7 +1152,7 @@ ZW=Zimbabwe 151=Eastern Europe 154=Northern Europe 155=Western Europe -419=Latin America and the Caribbean +419=Latin America # variant names # key is %%variant diff --git a/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index 845433becb1..3642db89871 100644 --- a/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -32,10 +32,13 @@ import java.net.Inet6Address; import java.net.InetSocketAddress; import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.channels.Channel; import java.nio.channels.spi.SelectorProvider; import static java.net.StandardProtocolFamily.INET6; import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.UNIX; class InheritedChannel { @@ -45,10 +48,10 @@ class InheritedChannel { private static final int SOCK_DGRAM = 2; // socket address type - private static final int AF_UNKNOWN = -1; - private static final int AF_INET = 1; - private static final int AF_INET6 = 2; - private static final int AF_UNIX = 3; + static final int AF_UNKNOWN = -1; + static final int AF_INET = 1; + static final int AF_INET6 = 2; + static final int AF_UNIX = 3; // oflag values when opening a file private static final int O_RDONLY = 0; @@ -75,6 +78,24 @@ private static void detachIOStreams() { } } + static ProtocolFamily protocolFamily(SocketAddress sa) { + if (sa instanceof UnixDomainSocketAddress) { + return UNIX; + } else { + InetSocketAddress isa = (InetSocketAddress) sa; + return (isa.getAddress() instanceof Inet6Address) ? INET6 : INET; + } + } + + static ProtocolFamily protocolFamily(int family) { + return switch (family) { + case AF_INET -> INET; + case AF_INET6 -> INET6; + case AF_UNIX -> UNIX; + default -> throw new IllegalArgumentException(); + }; + } + /* * Override the implCloseSelectableChannel for each channel type - this * allows us to "detach" the standard streams after closing and ensures @@ -82,16 +103,12 @@ private static void detachIOStreams() { */ public static class InheritedSocketChannelImpl extends SocketChannelImpl { - static ProtocolFamily family(InetSocketAddress isa) { - return (isa.getAddress() instanceof Inet6Address) ? INET6 : INET; - } - InheritedSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, - InetSocketAddress remote) + SocketAddress remote) throws IOException { - super(sp, family(remote), fd, remote); + super(sp, protocolFamily(remote), fd, remote); } protected void implCloseSelectableChannel() throws IOException { @@ -100,39 +117,24 @@ protected void implCloseSelectableChannel() throws IOException { } } - public static class InheritedUnixChannelImpl extends UnixDomainSocketChannelImpl { - - InheritedUnixChannelImpl(FileDescriptor fd) - throws IOException - { - super(fd); - } - - protected void implCloseSelectableChannel() throws IOException { - super.implCloseChannel(); - detachIOStreams(); - } - } - - public static class InheritedServerSocketChannelImpl extends - ServerSocketChannelImpl { + public static class InheritedServerSocketChannelImpl extends ServerSocketChannelImpl { InheritedServerSocketChannelImpl(SelectorProvider sp, + ProtocolFamily family, FileDescriptor fd) throws IOException { - super(sp, fd, true); + super(sp, family, fd, true); } + @Override protected void implCloseSelectableChannel() throws IOException { super.implCloseSelectableChannel(); detachIOStreams(); } - } - public static class InheritedDatagramChannelImpl extends - DatagramChannelImpl { + public static class InheritedDatagramChannelImpl extends DatagramChannelImpl { InheritedDatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) @@ -151,16 +153,13 @@ protected void implCloseSelectableChannel() throws IOException { * If there's a SecurityManager then check for the appropriate * RuntimePermission. */ - private static void checkAccess(Channel c) { + private static void checkAccess() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm.checkPermission( - new RuntimePermission("inheritedChannel") - ); + sm.checkPermission(new RuntimePermission("inheritedChannel")); } } - /* * If standard inherited channel is connected to a socket then return a Channel * of the appropriate type based standard input. @@ -197,7 +196,7 @@ private static Channel createChannel() throws IOException { // Now create the channel. If the socket is a streams socket then - // we see if tthere is a peer (ie: connected). If so, then we + // we see if there is a peer (ie: connected). If so, then we // create a SocketChannel, otherwise a ServerSocketChannel. // If the socket is a datagram socket then create a DatagramChannel @@ -209,19 +208,21 @@ private static Channel createChannel() throws IOException { int family = addressFamily(fdVal); if (family == AF_UNKNOWN) return null; + ProtocolFamily pfamily = protocolFamily(family); if (family == AF_UNIX) { if (isConnected(fdVal)) { - return new InheritedUnixChannelImpl(fd); + var sa = UnixDomainSocketAddress.of(unixPeerAddress(fdVal)); + return new InheritedSocketChannelImpl(provider, fd, sa); } else { - // listener. unsupported. - return null; + return new InheritedServerSocketChannelImpl(provider, pfamily, fd); } } - InetAddress ia = peerAddress0(fdVal); + InetAddress ia = inetPeerAddress0(fdVal); if (ia == null) { - c = new InheritedServerSocketChannelImpl(provider, fd); + c = new InheritedServerSocketChannelImpl(provider, pfamily, fd); } else { int port = peerPort0(fdVal); + assert port > 0; InetSocketAddress isa = new InetSocketAddress(ia, port); c = new InheritedSocketChannelImpl(provider, fd, isa); @@ -253,11 +254,15 @@ public static synchronized Channel getChannel() throws IOException { // if there is a channel then do the security check before // returning it. if (channel != null) { - checkAccess(channel); + checkAccess(); } return channel; } + private static String unixPeerAddress(int fd) throws IOException { + byte[] bytes = unixPeerAddress0(fd); + return new String(bytes); + } // -- Native methods -- @@ -268,7 +273,8 @@ public static synchronized Channel getChannel() throws IOException { private static native void close0(int fd) throws IOException; private static native int soType0(int fd); private static native int addressFamily(int fd); - private static native InetAddress peerAddress0(int fd); + private static native InetAddress inetPeerAddress0(int fd); + private static native byte[] unixPeerAddress0(int fd); private static native int peerPort0(int fd); // return true if socket is connected to a peer diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java deleted file mode 100644 index d54c881f089..00000000000 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.ch; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousCloseException; -import java.nio.channels.ByteChannel; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NotYetConnectedException; -import java.nio.channels.spi.AbstractInterruptibleChannel; -import java.util.Objects; -import java.util.concurrent.locks.ReentrantLock; - -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -class UnixDomainSocketChannelImpl - extends AbstractInterruptibleChannel - implements ByteChannel -{ - // Used to make native read and write calls - private static final NativeDispatcher nd = new SocketDispatcher(); - - // Our file descriptor object - private final FileDescriptor fd; - // Lock held by current reading or connecting thread - private final ReentrantLock readLock = new ReentrantLock(); - - // Lock held by current writing or connecting thread - private final ReentrantLock writeLock = new ReentrantLock(); - - // Lock for managing close state - private final Object stateLock = new Object(); - - // Channel state - private static final int ST_INUSE = 0; - private static final int ST_CLOSING = 1; - private static final int ST_CLOSED = 2; - private int state; - - // IDs of native threads doing reads and writes, for signalling - private long readerThread; - private long writerThread; - - UnixDomainSocketChannelImpl(FileDescriptor fd) - throws IOException - { - this.fd = fd; - } - - /** - * Checks that the channel is open. - * - * @throws ClosedChannelException if channel is closed (or closing) - */ - private void ensureOpen() throws ClosedChannelException { - if (!isOpen()) - throw new ClosedChannelException(); - } - - /** - * Closes the socket if there are no I/O operations in progress - */ - private boolean tryClose() throws IOException { - assert Thread.holdsLock(stateLock) && state == ST_CLOSING; - if (readerThread == 0 && writerThread == 0) { - state = ST_CLOSED; - nd.close(fd); - return true; - } else { - return false; - } - } - - /** - * Complete closure of pre-closed socket (release the file descriptor) - */ - private void tryFinishClose() { - try { - tryClose(); - } catch (IOException ignore) { } - } - - /** - * Marks the beginning of a read operation - * - * @throws ClosedChannelException if the channel is closed - * @throws NotYetConnectedException if the channel is not yet connected - */ - private void beginRead() throws ClosedChannelException { - // set hook for Thread.interrupt - begin(); - synchronized (stateLock) { - ensureOpen(); - readerThread = NativeThread.current(); - } - } - - /** - * Marks the end of a read operation that may have blocked. - * - * @throws AsynchronousCloseException if the channel was closed due to this - * thread being interrupted on a blocking read operation. - */ - private void endRead(boolean completed) - throws AsynchronousCloseException - { - synchronized (stateLock) { - readerThread = 0; - if (state == ST_CLOSING) { - tryFinishClose(); - } - } - end(completed); - } - - @Override - public int read(ByteBuffer buf) throws IOException { - Objects.requireNonNull(buf); - - readLock.lock(); - try { - int n = 0; - try { - beginRead(); - n = IOUtil.read(fd, buf, -1, nd); - while (IOStatus.okayToRetry(n) && isOpen()) { - park(Net.POLLIN, 0L); - n = IOUtil.read(fd, buf, -1, nd); - } - } finally { - endRead(n > 0); - } - return n; - } finally { - readLock.unlock(); - } - } - - /** - * Marks the beginning of a write operation that might block. - * - * @throws ClosedChannelException if the channel is closed - * @throws NotYetConnectedException if the channel is not yet connected - */ - private void beginWrite() throws ClosedChannelException { - begin(); - synchronized (stateLock) { - // set hook for Thread.interrupt - ensureOpen(); - writerThread = NativeThread.current(); - } - } - - /** - * Marks the end of a write operation that may have blocked. - * - * @throws AsynchronousCloseException if the channel was closed due to this - * thread being interrupted on a blocking write operation. - */ - private void endWrite(boolean completed) - throws AsynchronousCloseException - { - synchronized (stateLock) { - writerThread = 0; - if (state == ST_CLOSING) { - tryFinishClose(); - } - } - end(completed); - } - - void park(int event, long nanos) throws IOException { - long millis; - if (nanos <= 0) { - millis = -1; - } else { - millis = NANOSECONDS.toMillis(nanos); - } - Net.poll(fd, event, millis); - } - - @Override - public int write(ByteBuffer buf) throws IOException { - Objects.requireNonNull(buf); - - writeLock.lock(); - try { - int n = 0; - try { - beginWrite(); - n = IOUtil.write(fd, buf, -1, nd); - while (IOStatus.okayToRetry(n) && isOpen()) { - park(Net.POLLOUT, 0L); - n = IOUtil.write(fd, buf, -1, nd); - } - } finally { - endWrite(n > 0); - } - return n; - } finally { - writeLock.unlock(); - } - } - - /** - * Closes this channel - * - * If there is an I/O operation in progress then the socket is pre-closed - * and the I/O threads signalled, in which case the final close is deferred - * until all I/O operations complete. - */ - @Override - protected void implCloseChannel() throws IOException { - synchronized (stateLock) { - assert state == ST_INUSE; - state = ST_CLOSING; - if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (reader != 0 || writer != 0) { - nd.preClose(fd); - if (reader != 0) - NativeThread.signal(reader); - if (writer != 0) - NativeThread.signal(writer); - } - } - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(this.getClass().getSuperclass().getName()); - sb.append('['); - if (!isOpen()) - sb.append("closed"); - sb.append(']'); - return sb.toString(); - } -} diff --git a/src/java.base/share/classes/sun/nio/ch/Secrets.java b/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java similarity index 50% rename from src/java.base/share/classes/sun/nio/ch/Secrets.java rename to src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java index f76ab1d75a0..4fd3e5f6a48 100644 --- a/src/java.base/share/classes/sun/nio/ch/Secrets.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -25,39 +25,41 @@ package sun.nio.ch; -import java.nio.channels.SocketChannel; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.io.FileDescriptor; -import java.io.IOException; +import java.nio.charset.Charset; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.net.NetProperties; +import jdk.internal.util.StaticProperty; /** - * Provides access to implementation private constructors and methods. + * Platform specific utility functions */ +class UnixDomainSocketsUtil { + private UnixDomainSocketsUtil() { } -public final class Secrets { - private Secrets() { } - - private static SelectorProvider provider() { - SelectorProvider p = SelectorProvider.provider(); - if (!(p instanceof SelectorProviderImpl)) - throw new UnsupportedOperationException(); - return p; - } - - public static SocketChannel newSocketChannel(FileDescriptor fd) { - try { - return new SocketChannelImpl(provider(), fd, false); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } + static Charset getCharset() { + return Charset.defaultCharset(); } - public static ServerSocketChannel newServerSocketChannel(FileDescriptor fd) { - try { - return new ServerSocketChannelImpl(provider(), fd, false); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } + /** + * Return the temp directory for storing automatically bound + * server sockets. + * + * On UNIX we search the following directories in sequence: + * + * 1. ${jdk.net.unixdomain.tmpdir} if set as system property + * 2. ${jdk.net.unixdomain.tmpdir} if set as net property + * 3. ${java.io.tmpdir} system property + */ + static String getTempDir() { + PrivilegedAction action = () -> { + String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); + if (s != null && s.length() > 0) { + return s; + } else { + return StaticProperty.javaIoTmpDir(); + } + }; + return AccessController.doPrivileged(action); } } 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 87284a9feb7..0a927d01d71 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, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -557,4 +557,10 @@ protected String implProbeContentType(Path file) throws IOException { } }; } + + @Override + public byte[] getSunPathForSocketFile(Path obj) { + UnixPath file = UnixPath.toUnixPath(obj); + return file.getByteArrayForSysCalls(); + } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java index b7a9e7692f0..03054fd8dea 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ * Unix implementation of java.nio.file.attribute.UserPrincipal */ -class UnixUserPrincipals { +public class UnixUserPrincipals { private static User createSpecial(String name) { return new User(-1, name); } static final User SPECIAL_OWNER = createSpecial("OWNER@"); @@ -108,7 +108,7 @@ static class Group extends User implements GroupPrincipal { } // return UserPrincipal representing given uid - static User fromUid(int uid) { + public static User fromUid(int uid) { String name; try { name = Util.toString(getpwuid(uid)); @@ -119,7 +119,7 @@ static User fromUid(int uid) { } // return GroupPrincipal representing given gid - static Group fromGid(int gid) { + public static Group fromGid(int gid) { String name; try { name = Util.toString(getgrgid(gid)); diff --git a/src/java.base/unix/conf/net.properties b/src/java.base/unix/conf/net.properties new file mode 100644 index 00000000000..6d72511ad95 --- /dev/null +++ b/src/java.base/unix/conf/net.properties @@ -0,0 +1,15 @@ +# +# Default directory where automatically bound Unix domain server +# sockets are stored. Sockets are automatically bound when bound +# with a null address. +# +# On Unix the search order to determine this directory is: +# +# 1. System property jdk.net.unixdomain.tmpdir +# +# 2. Networking property jdk.net.unixdomain.tmpdir specified +# in this file (effective default) +# +# 3. System property java.io.tmpdir +# +jdk.net.unixdomain.tmpdir=/tmp diff --git a/src/java.base/unix/native/libnet/NetworkInterface.c b/src/java.base/unix/native/libnet/NetworkInterface.c index 0581b8e90ec..67f6004ecec 100644 --- a/src/java.base/unix/native/libnet/NetworkInterface.c +++ b/src/java.base/unix/native/libnet/NetworkInterface.c @@ -205,7 +205,6 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 jboolean isCopy; const char* name_utf; char *colonP; - char searchName[IFNAMESIZE]; jobject obj = NULL; if (name != NULL) { @@ -229,15 +228,11 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 // search the list of interfaces based on name, // if it is virtual sub interface search with parent first. - strncpy(searchName, name_utf, IFNAMESIZE); - searchName[IFNAMESIZE - 1] = '\0'; - colonP = strchr(searchName, ':'); - if (colonP != NULL) { - *colonP = '\0'; - } + colonP = strchr(name_utf, ':'); + size_t limit = colonP != NULL ? (size_t)(colonP - name_utf) : strlen(name_utf); curr = ifs; while (curr != NULL) { - if (strcmp(searchName, curr->name) == 0) { + if (strlen(curr->name) == limit && memcmp(name_utf, curr->name, limit) == 0) { break; } curr = curr->next; diff --git a/src/java.base/unix/native/libnio/ch/InheritedChannel.c b/src/java.base/unix/native/libnio/ch/InheritedChannel.c index f19068fb2fa..eb8abc2aee4 100644 --- a/src/java.base/unix/native/libnio/ch/InheritedChannel.c +++ b/src/java.base/unix/native/libnio/ch/InheritedChannel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,10 +34,11 @@ #include "jni.h" #include "jni_util.h" #include "net_util.h" +#include "nio_util.h" #include "sun_nio_ch_InheritedChannel.h" -static int matchFamily(SOCKETADDRESS *sa) { +static int toInetFamily(SOCKETADDRESS *sa) { return (sa->sa.sa_family == (ipv6_available() ? AF_INET6 : AF_INET)); } @@ -49,7 +50,7 @@ Java_sun_nio_ch_InheritedChannel_initIDs(JNIEnv *env, jclass cla) } JNIEXPORT jobject JNICALL -Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd) +Java_sun_nio_ch_InheritedChannel_inetPeerAddress0(JNIEnv *env, jclass cla, jint fd) { SOCKETADDRESS sa; socklen_t len = sizeof(SOCKETADDRESS); @@ -57,7 +58,7 @@ Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd) jint remote_port; if (getpeername(fd, &sa.sa, &len) == 0) { - if (matchFamily(&sa)) { + if (toInetFamily(&sa)) { remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); } } @@ -65,6 +66,21 @@ Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd) return remote_ia; } +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_ch_InheritedChannel_unixPeerAddress0(JNIEnv *env, jclass cla, jint fd) +{ + struct sockaddr_un sa; + socklen_t len = sizeof(struct sockaddr_un); + jobject remote_sa = NULL; + + if (getpeername(fd, (struct sockaddr *)&sa, &len) == 0) { + if (sa.sun_family == AF_UNIX) { + remote_sa = sockaddrToUnixAddressBytes(env, &sa, len); + } + } + return remote_sa; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd) { @@ -72,8 +88,8 @@ Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd) socklen_t len = sizeof(SOCKETADDRESS); jint remote_port = -1; - if (getpeername(fd, &sa.sa, &len) == 0) { - if (matchFamily(&sa)) { + if (getpeername(fd, (struct sockaddr *)&sa.sa, &len) == 0) { + if (toInetFamily(&sa)) { NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); } } diff --git a/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c b/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c new file mode 100644 index 00000000000..f0febabed6c --- /dev/null +++ b/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jni.h" +#include "java_props.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" +#include "sun_nio_ch_Net.h" +#include "nio_util.h" +#include "nio.h" + +/* Subtle platform differences in how unnamed sockets (empty path) + * are returned from getsockname() + */ +#ifdef MACOSX + #define ZERO_PATHLEN(len) (JNI_FALSE) +#else + #define ZERO_PATHLEN(len) (len == offsetof(struct sockaddr_un, sun_path)) +#endif + +jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, struct sockaddr_un *sa, socklen_t len) +{ + if (sa->sun_family == AF_UNIX) { + int namelen; + if (ZERO_PATHLEN(len)) { + namelen = 0; + } else { + namelen = strlen(sa->sun_path); + } + jbyteArray name = (*env)->NewByteArray(env, namelen); + if (namelen != 0) { + (*env)->SetByteArrayRegion(env, name, 0, namelen, (jbyte*)sa->sun_path); + if ((*env)->ExceptionOccurred(env)) { + return NULL; + } + } + return name; + } + return NULL; +} + +jint unixSocketAddressToSockaddr(JNIEnv *env, jbyteArray path, struct sockaddr_un *sa, int *len) +{ + memset(sa, 0, sizeof(struct sockaddr_un)); + sa->sun_family = AF_UNIX; + int ret; + const char* pname = (const char *)(*env)->GetByteArrayElements(env, path, NULL); + if (pname == NULL) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path not present"); + return -1; + } + size_t name_len = (*env)->GetArrayLength(env, path); + if (name_len > MAX_UNIX_DOMAIN_PATH_LEN) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path too long"); + ret = -1; + } else { + memcpy(sa->sun_path, pname, name_len); + *len = (int)(offsetof(struct sockaddr_un, sun_path) + name_len + 1); + ret = 0; + } + (*env)->ReleaseByteArrayElements(env, path, (jbyte *)pname, 0); + return ret; +} + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_UnixDomainSockets_socketSupported(JNIEnv *env, jclass cl) +{ + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_socket0(JNIEnv *env, jclass cl) +{ + int fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + return handleSocketError(env, errno); + } + return fd; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_UnixDomainSockets_bind0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray path) +{ + struct sockaddr_un sa; + int sa_len = 0; + int rv = 0; + + if (unixSocketAddressToSockaddr(env, path, &sa, &sa_len) != 0) + return; + + rv = bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); + if (rv != 0) { + handleSocketError(env, errno); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_connect0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray path) +{ + struct sockaddr_un sa; + int sa_len = 0; + int rv; + + if (unixSocketAddressToSockaddr(env, path, &sa, &sa_len) != 0) { + return IOS_THROWN; + } + + rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); + if (rv != 0) { + if (errno == EINPROGRESS) { + return IOS_UNAVAILABLE; + } else if (errno == EINTR) { + return IOS_INTERRUPTED; + } + return handleSocketError(env, errno); + } + return 1; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_accept0(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo, + jobjectArray array) +{ + jint fd = fdval(env, fdo); + jint newfd; + struct sockaddr_un sa; + socklen_t sa_len = sizeof(struct sockaddr_un); + jbyteArray address; + + newfd = accept(fd, (struct sockaddr *)&sa, &sa_len); + if (newfd < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + return IOS_UNAVAILABLE; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); + return IOS_THROWN; + } + + setfdval(env, newfdo, newfd); + + address = sockaddrToUnixAddressBytes(env, &sa, sa_len); + CHECK_NULL_RETURN(address, IOS_THROWN); + + (*env)->SetObjectArrayElement(env, array, 0, address); + + return 1; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_ch_UnixDomainSockets_localAddress0(JNIEnv *env, jclass clazz, jobject fdo) +{ + struct sockaddr_un sa; + socklen_t sa_len = sizeof(struct sockaddr_un); + int port; + if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { + handleSocketError(env, errno); + return NULL; + } + return sockaddrToUnixAddressBytes(env, &sa, sa_len); +} + diff --git a/src/java.base/unix/native/libnio/ch/nio_util.h b/src/java.base/unix/native/libnio/ch/nio_util.h index 5ebbdd7f859..5e20934678c 100644 --- a/src/java.base/unix/native/libnio/ch/nio_util.h +++ b/src/java.base/unix/native/libnio/ch/nio_util.h @@ -29,6 +29,7 @@ #include "jlong.h" #include #include +#include #define RESTARTABLE(_cmd, _result) do { \ do { \ @@ -47,6 +48,12 @@ #endif #endif +/* 2 bytes to allow for null at end of string and null at start of string + * for abstract name + */ +#define MAX_UNIX_DOMAIN_PATH_LEN \ + (int)(sizeof(((struct sockaddr_un *)0)->sun_path)-2) + /* NIO utility procedures */ @@ -62,3 +69,15 @@ jlong convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading); /* Defined in Net.c */ jint handleSocketError(JNIEnv *env, jint errorValue); + +/* Defined in UnixDomainSockets.c */ + +jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, + struct sockaddr_un *sa, + socklen_t len); + +jint unixSocketAddressToSockaddr(JNIEnv *env, + jbyteArray uaddr, + struct sockaddr_un *sa, + int *len); + diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java index 88510f231c8..57d0adb1959 100644 --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,14 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; import java.nio.*; import java.nio.channels.*; +import java.nio.file.Files; +import java.nio.file.Path; import java.nio.channels.spi.*; import java.security.AccessController; import java.security.PrivilegedExceptionAction; @@ -55,16 +61,17 @@ class PipeImpl private static final Random RANDOM_NUMBER_GENERATOR = new SecureRandom(); // Source and sink channels - private SourceChannel source; - private SinkChannel sink; + private final SourceChannel source; + private final SinkChannel sink; private class Initializer implements PrivilegedExceptionAction { private final SelectorProvider sp; - - private IOException ioe = null; + private IOException ioe; + SourceChannelImpl source; + SinkChannelImpl sink; private Initializer(SelectorProvider sp) { this.sp = sp; @@ -103,23 +110,20 @@ public void run() { ServerSocketChannel ssc = null; SocketChannel sc1 = null; SocketChannel sc2 = null; + // Loopback address + SocketAddress sa = null; try { // Create secret with a backing array. ByteBuffer secret = ByteBuffer.allocate(NUM_SECRET_BYTES); ByteBuffer bb = ByteBuffer.allocate(NUM_SECRET_BYTES); - // Loopback address - InetAddress lb = InetAddress.getLoopbackAddress(); - assert(lb.isLoopbackAddress()); - InetSocketAddress sa = null; for(;;) { // Bind ServerSocketChannel to a port on the loopback // address if (ssc == null || !ssc.isOpen()) { - ssc = ServerSocketChannel.open(); - ssc.socket().bind(new InetSocketAddress(lb, 0)); - sa = new InetSocketAddress(lb, ssc.socket().getLocalPort()); + ssc = createListener(); + sa = ssc.getLocalAddress(); } // Establish connection (assume connections are eagerly @@ -160,18 +164,43 @@ public void run() { try { if (ssc != null) ssc.close(); + if (sa instanceof UnixDomainSocketAddress) { + Path path = ((UnixDomainSocketAddress) sa).getPath(); + Files.deleteIfExists(path); + } } catch (IOException e2) {} } } } } - PipeImpl(final SelectorProvider sp) throws IOException { + /** + * Creates a Pipe implementation that supports buffering. + */ + PipeImpl(SelectorProvider sp) throws IOException { + this(sp, true); + } + + /** + * Creates Pipe implementation that supports optionally buffering. + * + * @implNote The pipe uses Unix domain sockets where possible. It uses a + * loopback connection on older editions of Windows. When buffering is + * disabled then it sets TCP_NODELAY on the sink channel. + */ + PipeImpl(SelectorProvider sp, boolean buffering) throws IOException { + Initializer initializer = new Initializer(sp); try { - AccessController.doPrivileged(new Initializer(sp)); - } catch (PrivilegedActionException x) { - throw (IOException)x.getCause(); + AccessController.doPrivileged(initializer); + SinkChannelImpl sink = initializer.sink; + if (sink.isNetSocket() && !buffering) { + sink.setOption(StandardSocketOptions.TCP_NODELAY, true); + } + } catch (PrivilegedActionException pae) { + throw (IOException) pae.getCause(); } + this.source = initializer.source; + this.sink = initializer.sink; } public SourceChannel source() { @@ -182,4 +211,25 @@ public SinkChannel sink() { return sink; } + private static volatile boolean noUnixDomainSockets; + + private static ServerSocketChannel createListener() throws IOException { + ServerSocketChannel listener = null; + if (!noUnixDomainSockets) { + try { + listener = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + return listener.bind(null); + } catch (UnsupportedOperationException | IOException e) { + // IOException is most likely to be caused by the temporary directory + // name being too long. Possibly should log this. + noUnixDomainSockets = true; + if (listener != null) + listener.close(); + } + } + listener = ServerSocketChannel.open(); + InetAddress lb = InetAddress.getLoopbackAddress(); + listener.bind(new InetSocketAddress(lb, 0)); + return listener; + } } diff --git a/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java index 66437deb87a..6b6352edac0 100644 --- a/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.FileDescriptor; +import java.net.SocketOption; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.channels.spi.*; @@ -44,19 +45,27 @@ class SinkChannelImpl implements SelChImpl { // The SocketChannel assoicated with this pipe - final SocketChannel sc; + private final SocketChannelImpl sc; public FileDescriptor getFD() { - return ((SocketChannelImpl)sc).getFD(); + return sc.getFD(); } public int getFDVal() { - return ((SocketChannelImpl)sc).getFDVal(); + return sc.getFDVal(); } SinkChannelImpl(SelectorProvider sp, SocketChannel sc) { super(sp); - this.sc = sc; + this.sc = (SocketChannelImpl) sc; + } + + boolean isNetSocket() { + return sc.isNetSocket(); + } + + void setOption(SocketOption name, T value) throws IOException { + sc.setOption(name, value); } protected void implCloseSelectableChannel() throws IOException { diff --git a/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java b/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java new file mode 100644 index 00000000000..ff1507f5931 --- /dev/null +++ b/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002, 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. + */ + +package sun.nio.ch; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.net.NetProperties; +import jdk.internal.util.StaticProperty; + +class UnixDomainSocketsUtil { + private UnixDomainSocketsUtil() { } + + static Charset getCharset() { + return StandardCharsets.UTF_8; + } + + /** + * Return the temp directory for storing automatically bound + * server sockets. + * + * On Windows we search the following directories in sequence: + * + * 1. ${jdk.net.unixdomain.tmpdir} if set as system property + * 2. ${jdk.net.unixdomain.tmpdir} if set as net property + * 3. %TEMP% + * 4. ${java.io.tmpdir} + */ + static String getTempDir() { + PrivilegedAction action = () -> { + String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); + if (s != null) { + return s; + } + String temp = System.getenv("TEMP"); + if (temp != null) { + return temp; + } + return StaticProperty.javaIoTmpDir(); + }; + return AccessController.doPrivileged(action); + } +} + diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index f5f73da1eec..328437cefb9 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.nio.channels.Pipe; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; +import java.nio.channels.SelectableChannel; import java.nio.channels.spi.SelectorProvider; import java.util.ArrayDeque; import java.util.ArrayList; @@ -139,14 +140,9 @@ private static final class MapEntry { WindowsSelectorImpl(SelectorProvider sp) throws IOException { super(sp); pollWrapper = new PollArrayWrapper(INIT_CAP); - wakeupPipe = Pipe.open(); + wakeupPipe = new PipeImpl(sp, false); wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFDVal(); - - // Disable the Nagle algorithm so that the wakeup is more immediate - SinkChannelImpl sink = (SinkChannelImpl)wakeupPipe.sink(); - (sink.sc).socket().setTcpNoDelay(true); - wakeupSinkFd = ((SelChImpl)sink).getFDVal(); - + wakeupSinkFd = ((SelChImpl)wakeupPipe.sink()).getFDVal(); pollWrapper.addWakeupSocket(wakeupSourceFd, 0); } @@ -413,19 +409,19 @@ private int processFDSet(long updateCount, // processDeregisterQueue. if (me == null) continue; - SelectionKeyImpl sk = me.ski; + SelectionKeyImpl ski = me.ski; // The descriptor may be in the exceptfds set because there is // OOB data queued to the socket. If there is OOB data then it // is discarded and the key is not added to the selected set. - if (isExceptFds && - (sk.channel() instanceof SocketChannelImpl) && - discardUrgentData(desc)) - { + SelectableChannel sc = ski.channel(); + if (isExceptFds && (sc instanceof SocketChannelImpl) + && ((SocketChannelImpl) sc).isNetSocket() + && discardUrgentData(desc)) { continue; } - int updated = processReadyEvents(rOps, sk, action); + int updated = processReadyEvents(rOps, ski, action); if (updated > 0 && me.updateCount != updateCount) { me.updateCount = updateCount; numKeysUpdated++; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java index ad3ec2d7e3c..0435e17c1b5 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.nio.channels.*; +import java.nio.charset.StandardCharsets; import java.net.URI; import java.util.concurrent.ExecutorService; import java.io.*; @@ -622,4 +623,12 @@ public Path readSymbolicLink(Path obj1) throws IOException { String target = WindowsLinkSupport.readLink(link); return WindowsPath.createFromNormalizedPath(fs, target); } + + @Override + public byte[] getSunPathForSocketFile(Path obj) { + WindowsPath file = WindowsPath.toWindowsPath(obj); + String s = file.toString(); + return s.getBytes(StandardCharsets.UTF_8); + } + } diff --git a/src/java.base/windows/conf/net.properties b/src/java.base/windows/conf/net.properties new file mode 100644 index 00000000000..04598400a5e --- /dev/null +++ b/src/java.base/windows/conf/net.properties @@ -0,0 +1,19 @@ +# +# Default directory where automatically bound Unix domain server +# sockets are stored. Sockets are automatically bound when bound +# with a null address. +# +# The search order for the directory on Windows is: +# +# 1. System property "jdk.net.unixdomain.tmpdir" +# +# 2. Networking property "jdk.net.unixdomain.tmpdir" specified +# in this file (not set by default) +# +# 3. The TEMP environment variable (the effective default) +# +# 4. The java.io.tmpdir system property +# +#jdk.net.unixdomain.tmpdir= +# + diff --git a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c new file mode 100644 index 00000000000..1869009a1f9 --- /dev/null +++ b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" +#include "nio.h" +#include "nio_util.h" +#include "net_util.h" + +#include "java_net_InetAddress.h" +#include "sun_nio_ch_Net.h" +#include "sun_nio_ch_PollArrayWrapper.h" + +jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, struct sockaddr_un *sa, socklen_t len) +{ + if (sa->sun_family == AF_UNIX) { + int namelen = (int)strlen(sa->sun_path); + jbyteArray name = (*env)->NewByteArray(env, namelen); + if (name != NULL) { + (*env)->SetByteArrayRegion(env, name, 0, namelen, (jbyte*)sa->sun_path); + if ((*env)->ExceptionOccurred(env)) { + return NULL; + } + } + return name; + } + return NULL; +} + +jint unixSocketAddressToSockaddr(JNIEnv *env, jbyteArray addr, struct sockaddr_un *sa, int *len) +{ + memset(sa, 0, sizeof(struct sockaddr_un)); + sa->sun_family = AF_UNIX; + if (addr == 0L) { + /* Do explicit bind on Windows */ + *len = (int)(offsetof(struct sockaddr_un, sun_path)); + return 0; + } + int ret; + jboolean isCopy; + char *pname = (*env)->GetByteArrayElements(env, addr, &isCopy); + if (pname == NULL) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path not present"); + return -1; + } + + size_t name_len = (size_t)(*env)->GetArrayLength(env, addr); + if (name_len > MAX_UNIX_DOMAIN_PATH_LEN) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path too long"); + ret = -1; + } else { + strncpy(sa->sun_path, pname, name_len); + *len = (int)(offsetof(struct sockaddr_un, sun_path) + name_len); + ret = 0; + } + (*env)->ReleaseByteArrayElements(env, addr, pname, JNI_ABORT); + return ret; +} + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_UnixDomainSockets_socketSupported(JNIEnv *env, jclass cl) +{ + SOCKET s = socket(PF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + return JNI_FALSE; + } + closesocket(s); + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_socket0(JNIEnv *env, jclass cl) +{ + SOCKET s = socket(PF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + return handleSocketError(env, WSAGetLastError()); + } + SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); + return (int)s; +} + +/** + * Windows does not support auto bind. So, the windows version of unixSocketAddressToSockaddr + * looks out for a null 'uaddr' and handles it specially + */ +JNIEXPORT void JNICALL +Java_sun_nio_ch_UnixDomainSockets_bind0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray addr) +{ + struct sockaddr_un sa; + int sa_len = 0; + int rv = 0; + + if (unixSocketAddressToSockaddr(env, addr, &sa, &sa_len) != 0) + return; + + rv = bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); + if (rv == SOCKET_ERROR) { + int err = WSAGetLastError(); + NET_ThrowNew(env, err, "bind"); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_connect0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray addr) +{ + struct sockaddr_un sa; + int sa_len = 0; + int rv; + + if (unixSocketAddressToSockaddr(env, addr, &sa, &sa_len) != 0) { + return IOS_THROWN; + } + + rv = connect(fdval(env, fdo), (const struct sockaddr *)&sa, sa_len); + if (rv != 0) { + int err = WSAGetLastError(); + if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) { + return IOS_UNAVAILABLE; + } + NET_ThrowNew(env, err, "connect"); + return IOS_THROWN; + } + return 1; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixDomainSockets_accept0(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo, + jobjectArray array) +{ + jint fd = fdval(env, fdo); + jint newfd; + struct sockaddr_un sa; + socklen_t sa_len = sizeof(sa); + jbyteArray address; + + memset((char *)&sa, 0, sizeof(sa)); + newfd = (jint) accept(fd, (struct sockaddr *)&sa, &sa_len); + if (newfd == INVALID_SOCKET) { + int theErr = (jint)WSAGetLastError(); + if (theErr == WSAEWOULDBLOCK) { + return IOS_UNAVAILABLE; + } + JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); + return IOS_THROWN; + } + + SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); + setfdval(env, newfdo, newfd); + + address = sockaddrToUnixAddressBytes(env, &sa, sa_len); + CHECK_NULL_RETURN(address, IOS_THROWN); + (*env)->SetObjectArrayElement(env, array, 0, address); + + return 1; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_ch_UnixDomainSockets_localAddress0(JNIEnv *env, jclass clazz, jobject fdo) +{ + struct sockaddr_un sa; + int sa_len = sizeof(sa); + + if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) == SOCKET_ERROR) { + JNU_ThrowIOExceptionWithLastError(env, "getsockname"); + return NULL; + } + return sockaddrToUnixAddressBytes(env, &sa, sa_len); +} + diff --git a/src/java.base/windows/native/libnio/ch/nio_util.h b/src/java.base/windows/native/libnio/ch/nio_util.h index 8a1cf562e33..750bc4d61df 100644 --- a/src/java.base/windows/native/libnio/ch/nio_util.h +++ b/src/java.base/windows/native/libnio/ch/nio_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ */ #include +#include +#include #include "jni.h" @@ -35,6 +37,9 @@ */ #define MAX_BUFFER_SIZE ((128*1024)-1) +#define MAX_UNIX_DOMAIN_PATH_LEN \ + (int)(sizeof(((struct sockaddr_un *)0)->sun_path)-2) + jint fdval(JNIEnv *env, jobject fdo); void setfdval(JNIEnv *env, jobject fdo, jint val); jlong handleval(JNIEnv *env, jobject fdo); @@ -74,3 +79,11 @@ struct iovec { /* POLLCONN must not equal any of the other constants (see winsock2.h). */ #define POLLCONN 0x2000 #endif + +/* Defined in UnixDomainSockets.c */ + +jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, struct sockaddr_un *sa, socklen_t len); + +jint unixSocketAddressToSockaddr(JNIEnv *env, jbyteArray uaddr, + struct sockaddr_un *sa, int *len); + diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java index 28af5334e9f..c16a4c7f978 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java @@ -109,33 +109,15 @@ public enum ElementKind { MODULE, /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This enum constant is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A record type. - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) RECORD, /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This enum constant is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A record component of a {@code record}. - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) RECORD_COMPONENT, /** diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java b/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java index 440a9e156fe..44635fa62d3 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java @@ -211,13 +211,6 @@ default R visitModule(ModuleElement e, P p) { } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Visits a record component element. * * @implSpec The default implementation visits a {@code @@ -226,11 +219,8 @@ default R visitModule(ModuleElement e, P p) { * @param e the element to visit * @param p a visitor-specified parameter * @return a visitor-specified result - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") default R visitRecordComponent(RecordComponentElement e, P p) { return visitUnknown(e, p); } diff --git a/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java b/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java index be4bd7c2680..c4e781baade 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java @@ -26,19 +26,10 @@ package javax.lang.model.element; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Represents a record component. * - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) public interface RecordComponentElement extends Element { /** * Returns the enclosing element of this record component. diff --git a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java index 0be3401bbc4..836ad989c35 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java @@ -180,13 +180,6 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable List getTypeParameters(); /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns the record components of this type element in * declaration order. * @@ -196,11 +189,8 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable * @return the record components, or an empty list if there are * none * - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") default List getRecordComponents() { return List.of(); } diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java index 051479f9208..3f0126b2ce1 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java @@ -31,13 +31,6 @@ import static javax.lang.model.SourceVersion.*; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A skeletal visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_14 RELEASE_14} * source version. @@ -54,10 +47,8 @@ * @see AbstractElementVisitor7 * @see AbstractElementVisitor8 * @see AbstractElementVisitor9 - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) @SupportedSourceVersion(RELEASE_16) public abstract class AbstractElementVisitor14 extends AbstractElementVisitor9 { /** @@ -77,7 +68,6 @@ protected AbstractElementVisitor14(){ * @param p {@inheritDoc} * @return {@inheritDoc} */ - @SuppressWarnings("preview") @Override public abstract R visitRecordComponent(RecordComponentElement t, P p); } diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java index 7cb58c943a9..270074f0d52 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java @@ -112,42 +112,22 @@ private ElementFilter() {} // Do not instantiate. } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns a list of record components in {@code elements}. * @return a list of record components in {@code elements} * @param elements the elements to filter - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") public static List recordComponentsIn(Iterable elements) { return listFilter(elements, RECORD_COMPONENT_KIND, RecordComponentElement.class); } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns a set of record components in {@code elements}. * @return a set of record components in {@code elements} * @param elements the elements to filter - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") public static Set recordComponentsIn(Set elements) { return setFilter(elements, RECORD_COMPONENT_KIND, RecordComponentElement.class); diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java index 1e7c92e1567..fd96c6ecad6 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java @@ -31,13 +31,6 @@ import javax.lang.model.SourceVersion; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A visitor of program elements based on their {@linkplain * ElementKind kind} with default behavior appropriate for the {@link * SourceVersion#RELEASE_14 RELEASE_14} source version. @@ -66,10 +59,8 @@ * @see ElementKindVisitor7 * @see ElementKindVisitor8 * @see ElementKindVisitor9 - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) @SupportedSourceVersion(RELEASE_16) public class ElementKindVisitor14 extends ElementKindVisitor9 { /** @@ -99,7 +90,6 @@ protected ElementKindVisitor14(R defaultValue) { * @param p a visitor-specified parameter * @return the result of {@code defaultAction} */ - @SuppressWarnings("preview") @Override public R visitRecordComponent(RecordComponentElement e, P p) { return defaultAction(e, p); diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java index 356accba1e0..3d40feed869 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java @@ -217,13 +217,6 @@ public R visitTypeAsInterface(TypeElement e, P p) { } /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Visits a {@code RECORD} type element. * * @implSpec This implementation calls {@code visitUnknown}. @@ -232,10 +225,8 @@ public R visitTypeAsInterface(TypeElement e, P p) { * @param p a visitor-specified parameter * @return the result of {@code visitUnknown} * - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) public R visitTypeAsRecord(TypeElement e, P p) { return visitUnknown(e, p); } 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 d0e92f911f5..5e5d484fa83 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 @@ -33,13 +33,6 @@ import static javax.lang.model.SourceVersion.*; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A scanning visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_14 RELEASE_14} * source version. @@ -81,10 +74,8 @@ * @see ElementScanner7 * @see ElementScanner8 * @see ElementScanner9 - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) @SupportedSourceVersion(RELEASE_16) public class ElementScanner14 extends ElementScanner9 { /** @@ -156,7 +147,6 @@ private List createScanningList(Parameterizable element, * @param p a visitor-specified parameter * @return the result of the scan */ - @SuppressWarnings("preview") @Override public R visitRecordComponent(RecordComponentElement e, P p) { return scan(e.getEnclosedElements(), p); diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java index ef00175d454..bf64e4f34b9 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java @@ -632,13 +632,6 @@ boolean overrides(ExecutableElement overrider, ExecutableElement overridden, boolean isFunctionalInterface(TypeElement type); /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This method is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Returns the record component for the given accessor. Returns null if the * given method is not a record component accessor. * @@ -653,11 +646,8 @@ boolean overrides(ExecutableElement overrider, ExecutableElement overridden, * @param accessor the method for which the record component should be found. * @return the record component, or null if the given method is not an record * component accessor - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) - @SuppressWarnings("preview") default RecordComponentElement recordComponentFor(ExecutableElement accessor) { if (accessor.getEnclosingElement().getKind() == ElementKind.RECORD) { for (RecordComponentElement rec : ElementFilter.recordComponentsIn(accessor.getEnclosingElement().getEnclosedElements())) { diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java index 5d0768eb0b0..9150f27d0fe 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java @@ -31,13 +31,6 @@ import static javax.lang.model.SourceVersion.*; /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This class is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * A simple visitor of program elements with default behavior * appropriate for the {@link SourceVersion#RELEASE_14 RELEASE_14} * source version. @@ -62,10 +55,8 @@ * @see SimpleElementVisitor7 * @see SimpleElementVisitor8 * @see SimpleElementVisitor9 - * @since 14 + * @since 16 */ -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) @SupportedSourceVersion(RELEASE_16) public class SimpleElementVisitor14 extends SimpleElementVisitor9 { /** @@ -96,7 +87,6 @@ protected SimpleElementVisitor14(R defaultValue){ * @param p a visitor-specified parameter * @return {@inheritDoc} */ - @SuppressWarnings("preview") @Override public R visitRecordComponent(RecordComponentElement e, P p) { return defaultAction(e, p); diff --git a/src/java.desktop/share/classes/java/awt/EventQueue.java b/src/java.desktop/share/classes/java/awt/EventQueue.java index 9ee82f2e2f0..0e19ab5483a 100644 --- a/src/java.desktop/share/classes/java/awt/EventQueue.java +++ b/src/java.desktop/share/classes/java/awt/EventQueue.java @@ -95,7 +95,7 @@ * @since 1.1 */ public class EventQueue { - private static final AtomicInteger threadInitNumber = new AtomicInteger(0); + private static final AtomicInteger threadInitNumber = new AtomicInteger(); private static final int LOW_PRIORITY = 0; private static final int NORM_PRIORITY = 1; diff --git a/src/java.desktop/share/classes/java/awt/color/ColorSpace.java b/src/java.desktop/share/classes/java/awt/color/ColorSpace.java index 24978e1917f..ecb40c2844f 100644 --- a/src/java.desktop/share/classes/java/awt/color/ColorSpace.java +++ b/src/java.desktop/share/classes/java/awt/color/ColorSpace.java @@ -102,12 +102,12 @@ public abstract class ColorSpace implements Serializable { /** * One of the {@code ColorSpace} type constants. */ - private int type; + private final int type; /** * The number of components in the color space. */ - private int numComponents; + private final int numComponents; private transient String [] compName = null; // Cache of singletons for the predefined color spaces. @@ -242,6 +242,7 @@ public abstract class ColorSpace implements Serializable { */ @Native public static final int TYPE_FCLR = 25; + /** * The sRGB color space defined at * @@ -275,11 +276,11 @@ public abstract class ColorSpace implements Serializable { * number of components. * * @param type one of the {@code ColorSpace} type constants - * @param numcomponents the number of components in the color space + * @param numComponents the number of components in the color space */ - protected ColorSpace(int type, int numcomponents) { + protected ColorSpace(int type, int numComponents) { this.type = type; - this.numComponents = numcomponents; + this.numComponents = numComponents; } /** @@ -441,8 +442,8 @@ public boolean isCS_sRGB () { * {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of * {@code ICC_ColorSpace} for further information. * - * @param colorvalue a float array with length of at least the number of - * components in this {@code ColorSpace} + * @param colorvalue a float array with length of at least the number of + * components in this {@code ColorSpace} * @return a float array of length 3 * @throws ArrayIndexOutOfBoundsException if array length is not at least * the number of components in this {@code ColorSpace}. @@ -508,11 +509,7 @@ public int getNumComponents() { */ public String getName (int idx) { /* REMIND - handle common cases here */ - if ((idx < 0) || (idx > numComponents - 1)) { - throw new IllegalArgumentException( - "Component index out of range: " + idx); - } - + rangeCheck(idx); if (compName == null) { switch (type) { case ColorSpace.TYPE_XYZ: @@ -573,10 +570,7 @@ public String getName (int idx) { * @since 1.4 */ public float getMinValue(int component) { - if ((component < 0) || (component > numComponents - 1)) { - throw new IllegalArgumentException( - "Component index out of range: " + component); - } + rangeCheck(component); return 0.0f; } @@ -592,17 +586,21 @@ public float getMinValue(int component) { * @since 1.4 */ public float getMaxValue(int component) { - if ((component < 0) || (component > numComponents - 1)) { - throw new IllegalArgumentException( - "Component index out of range: " + component); - } + rangeCheck(component); return 1.0f; } - /* - * Returns {@code true} if {@code cspace} is the XYZspace. + /** + * Checks that {@code component} is in range of the number of components. + * + * @param component the component index + * @throws IllegalArgumentException if component is less than 0 or greater + * than {@code numComponents - 1} */ - static boolean isCS_CIEXYZ(ColorSpace cspace) { - return (cspace == XYZspace); + final void rangeCheck(int component) { + if (component < 0 || component > getNumComponents() - 1) { + throw new IllegalArgumentException( + "Component index out of range: " + component); + } } } diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java b/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java index 6b399f66723..73b5f1ebb92 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java @@ -569,10 +569,7 @@ public float[] fromCIEXYZ(float[] colorvalue) { * @since 1.4 */ public float getMinValue(int component) { - if ((component < 0) || (component > this.getNumComponents() - 1)) { - throw new IllegalArgumentException( - "Component index out of range: " + component); - } + rangeCheck(component); return minVal[component]; } @@ -595,10 +592,7 @@ public float getMinValue(int component) { * @since 1.4 */ public float getMaxValue(int component) { - if ((component < 0) || (component > this.getNumComponents() - 1)) { - throw new IllegalArgumentException( - "Component index out of range: " + component); - } + rangeCheck(component); return maxVal[component]; } 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 66cc81ac8f8..fdc6b51c060 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 @@ -115,10 +115,7 @@ public float[] getMediaWhitePoint() { * single gamma value */ public float getGamma() { - float theGamma; - - theGamma = super.getGamma(ICC_Profile.icSigGrayTRCTag); - return theGamma; + return getGamma(ICC_Profile.icSigGrayTRCTag); } /** @@ -140,10 +137,6 @@ public float getGamma() { * table */ public short[] getTRC() { - short[] theTRC; - - theTRC = super.getTRC(ICC_Profile.icSigGrayTRCTag); - return theTRC; + return getTRC(ICC_Profile.icSigGrayTRCTag); } - } 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 12827c0b465..a316b98522e 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 @@ -103,7 +103,7 @@ public class ICC_ProfileRGB extends ICC_Profile { /** * Constructs an new {@code ICC_ProfileRGB} from a CMM ID. * - * @param p the CMM ID for the profile. + * @param p the CMM ID for the profile. */ ICC_ProfileRGB(Profile p) { super(p); @@ -113,7 +113,7 @@ public class ICC_ProfileRGB extends ICC_Profile { * Constructs a new {@code ICC_ProfileRGB} from a * {@code ProfileDeferralInfo} object. * - * @param pdi + * @param pdi */ ICC_ProfileRGB(ProfileDeferralInfo pdi) { super(pdi); @@ -143,22 +143,12 @@ public float[] getMediaWhitePoint() { * {@code greenColorantTag}, and {@code blueColorantTag} */ public float[][] getMatrix() { - float[][] theMatrix = new float[3][3]; - float[] tmpMatrix; - - tmpMatrix = getXYZTag(ICC_Profile.icSigRedColorantTag); - theMatrix[0][0] = tmpMatrix[0]; - theMatrix[1][0] = tmpMatrix[1]; - theMatrix[2][0] = tmpMatrix[2]; - tmpMatrix = getXYZTag(ICC_Profile.icSigGreenColorantTag); - theMatrix[0][1] = tmpMatrix[0]; - theMatrix[1][1] = tmpMatrix[1]; - theMatrix[2][1] = tmpMatrix[2]; - tmpMatrix = getXYZTag(ICC_Profile.icSigBlueColorantTag); - theMatrix[0][2] = tmpMatrix[0]; - theMatrix[1][2] = tmpMatrix[1]; - theMatrix[2][2] = tmpMatrix[2]; - return theMatrix; + float[] red = getXYZTag(ICC_Profile.icSigRedColorantTag); + float[] green = getXYZTag(ICC_Profile.icSigGreenColorantTag); + float[] blue = getXYZTag(ICC_Profile.icSigBlueColorantTag); + return new float[][]{{red[0], green[0], blue[0]}, + {red[1], green[1], blue[1]}, + {red[2], green[2], blue[2]}}; } /** @@ -181,33 +171,14 @@ public float[][] getMatrix() { * @param component the {@code ICC_ProfileRGB} constant that represents the * component whose TRC you want to retrieve * @return the gamma value as a float + * @throws IllegalArgumentException if the component is not + * {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or + * {@code BLUECOMPONENT} * @throws ProfileDataException if the profile does not specify the * corresponding TRC as a single gamma value */ public float getGamma(int component) { - float theGamma; - int theSignature; - - switch (component) { - case REDCOMPONENT: - theSignature = ICC_Profile.icSigRedTRCTag; - break; - - case GREENCOMPONENT: - theSignature = ICC_Profile.icSigGreenTRCTag; - break; - - case BLUECOMPONENT: - theSignature = ICC_Profile.icSigBlueTRCTag; - break; - - default: - throw new IllegalArgumentException("Must be Red, Green, or Blue"); - } - - theGamma = super.getGamma(theSignature); - - return theGamma; + return super.getGamma(toTag(component)); } /** @@ -232,33 +203,32 @@ public float getGamma(int component) { * component whose TRC you want to retrieve: {@code REDCOMPONENT}, * {@code GREENCOMPONENT}, or {@code BLUECOMPONENT} * @return a short array representing the TRC + * @throws IllegalArgumentException if the component is not + * {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or + * {@code BLUECOMPONENT} * @throws ProfileDataException if the profile does not specify the * corresponding TRC as a table */ public short[] getTRC(int component) { - short[] theTRC; - int theSignature; - - switch (component) { - case REDCOMPONENT: - theSignature = ICC_Profile.icSigRedTRCTag; - break; - - case GREENCOMPONENT: - theSignature = ICC_Profile.icSigGreenTRCTag; - break; - - case BLUECOMPONENT: - theSignature = ICC_Profile.icSigBlueTRCTag; - break; - - default: - throw new IllegalArgumentException("Must be Red, Green, or Blue"); - } - - theTRC = super.getTRC(theSignature); - - return theTRC; + return super.getTRC(toTag(component)); } + /** + * Converts the {@code ICC_ProfileRGB} constant to the appropriate tag. + * + * @param component the {@code ICC_ProfileRGB} constant + * @return the tag signature + * @throws IllegalArgumentException if the component is not + * {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or + * {@code BLUECOMPONENT} + */ + private static int toTag(int component) { + return switch (component) { + case REDCOMPONENT -> ICC_Profile.icSigRedTRCTag; + case GREENCOMPONENT -> ICC_Profile.icSigGreenTRCTag; + case BLUECOMPONENT -> ICC_Profile.icSigBlueTRCTag; + default -> throw new IllegalArgumentException( + "Must be Red, Green, or Blue"); + }; + } } diff --git a/src/java.desktop/share/classes/javax/swing/TimerQueue.java b/src/java.desktop/share/classes/javax/swing/TimerQueue.java index 9160b956e95..85e5b3a6aa1 100644 --- a/src/java.desktop/share/classes/javax/swing/TimerQueue.java +++ b/src/java.desktop/share/classes/javax/swing/TimerQueue.java @@ -248,7 +248,7 @@ static class DelayedTimer implements Delayed { * Sequence number to break scheduling ties, and in turn to * guarantee FIFO order among tied entries. */ - private static final AtomicLong sequencer = new AtomicLong(0); + private static final AtomicLong sequencer = new AtomicLong(); /** Sequence number to break ties FIFO */ private final long sequenceNumber; diff --git a/src/java.desktop/share/classes/sun/awt/AppContext.java b/src/java.desktop/share/classes/sun/awt/AppContext.java index cc4547ddc02..b8d902801a9 100644 --- a/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -208,7 +208,7 @@ public boolean isDisposed() { * number is 1. If so, it returns the sole AppContext without * checking Thread.currentThread(). */ - private static final AtomicInteger numAppContexts = new AtomicInteger(0); + private static final AtomicInteger numAppContexts = new AtomicInteger(); /* 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 1d47520a23d..dc9c2a0eb0e 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 @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "jni_util.h" #include "awt_p.h" #include "awt.h" @@ -31,14 +35,12 @@ #include #include #include -#ifndef HEADLESS #include #include #ifndef NO_XRANDR #include #endif #include "GLXGraphicsConfig.h" -#endif /* !HEADLESS */ #include #include @@ -54,8 +56,6 @@ #include #include "Trace.h" -#ifndef HEADLESS - int awt_numScreens; /* Xinerama-aware number of screens */ AwtScreenDataPtr x11Screens; @@ -66,12 +66,6 @@ AwtScreenDataPtr x11Screens; */ static jboolean glxRequested = JNI_FALSE; -#endif /* !HEADLESS */ - -#ifdef HEADLESS -#define Display void -#endif /* HEADLESS */ - Display *awt_display; jclass tkClass = NULL; @@ -92,9 +86,7 @@ jboolean awtLockInited = JNI_FALSE; struct X11GraphicsConfigIDs x11GraphicsConfigIDs; -#ifndef HEADLESS int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata); -#endif /* HEADLESS */ static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig"; @@ -134,8 +126,6 @@ Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls) CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel); } -#ifndef HEADLESS - /* * XIOErrorHandler */ @@ -593,8 +583,6 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { AWT_UNLOCK (); } -#ifndef HEADLESS - /* * Checks if Xinerama is running and perform Xinerama-related initialization. */ @@ -656,7 +644,6 @@ static void xineramaInit(void) { DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror()); } } -#endif /* HEADLESS */ Display * awt_init_Display(JNIEnv *env, jobject this) @@ -733,7 +720,6 @@ awt_init_Display(JNIEnv *env, jobject this) return dpy; } -#endif /* !HEADLESS */ /* * Class: sun_awt_X11GraphicsEnvironment @@ -744,14 +730,9 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum( JNIEnv *env, jobject this) { -#ifdef HEADLESS - return (jint)0; -#else return DefaultScreen(awt_display); -#endif /* !HEADLESS */ } -#ifndef HEADLESS static void ensureConfigsInited(JNIEnv* env, int screen) { if (x11Screens[screen].numConfigs == 0) { if (env == NULL) { @@ -760,19 +741,12 @@ static void ensureConfigsInited(JNIEnv* env, int screen) { getAllConfigs (env, screen, &(x11Screens[screen])); } } -#endif -#ifdef HEADLESS -void* getDefaultConfig(int screen) { - return NULL; -} -#else AwtGraphicsConfigDataPtr getDefaultConfig(int screen) { ensureConfigsInited(NULL, screen); return x11Screens[screen].defaultConfig; } -#endif /* !HEADLESS */ /* * Class: sun_awt_X11GraphicsEnvironment @@ -783,10 +757,8 @@ JNIEXPORT void JNICALL Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this, jboolean glxReq) { -#ifndef HEADLESS glxRequested = glxReq; (void) awt_init_Display(env, this); -#endif /* !HEADLESS */ } /* @@ -797,7 +769,6 @@ Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this, JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge) { -#ifndef HEADLESS jboolean glxAvailable; AWT_LOCK(); @@ -805,9 +776,6 @@ Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge) AWT_UNLOCK(); return glxAvailable; -#else - return JNI_FALSE; -#endif /* !HEADLESS */ } /* @@ -818,11 +786,7 @@ Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge) JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this) { -#ifdef HEADLESS - return (jint)0; -#else return awt_numScreens; -#endif /* !HEADLESS */ } /* @@ -833,11 +797,7 @@ Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this) JNIEXPORT jlong JNICALL Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this) { -#ifdef HEADLESS - return NULL; -#else return ptr_to_jlong(awt_display); -#endif /* !HEADLESS */ } #ifdef MITSHM @@ -964,11 +924,7 @@ JNIEXPORT jstring JNICALL Java_sun_awt_X11GraphicsEnvironment_getDisplayString (JNIEnv *env, jobject this) { -#ifdef HEADLESS - return (jstring)NULL; -#else return (*env)->NewStringUTF(env, DisplayString(awt_display)); -#endif /* HEADLESS */ } @@ -981,12 +937,8 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsDevice_getNumConfigs( JNIEnv *env, jobject this, jint screen) { -#ifdef HEADLESS - return (jint)0; -#else ensureConfigsInited(env, screen); return x11Screens[screen].numConfigs; -#endif /* !HEADLESS */ } /* @@ -998,9 +950,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsDevice_getConfigVisualId( JNIEnv *env, jobject this, jint index, jint screen) { -#ifdef HEADLESS - return (jint)0; -#else int visNum; ensureConfigsInited(env, screen); @@ -1009,7 +958,6 @@ JNIEnv *env, jobject this, jint index, jint screen) } else { return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid); } -#endif /* !HEADLESS */ } /* @@ -1021,9 +969,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsDevice_getConfigDepth( JNIEnv *env, jobject this, jint index, jint screen) { -#ifdef HEADLESS - return (jint)0; -#else int visNum; ensureConfigsInited(env, screen); @@ -1032,7 +977,6 @@ JNIEnv *env, jobject this, jint index, jint screen) } else { return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth); } -#endif /* !HEADLESS */ } /* @@ -1044,9 +988,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsDevice_getConfigColormap( JNIEnv *env, jobject this, jint index, jint screen) { -#ifdef HEADLESS - return (jint)0; -#else int visNum; ensureConfigsInited(env, screen); @@ -1055,7 +996,6 @@ JNIEnv *env, jobject this, jint index, jint screen) } else { return ((jint)x11Screens[screen].configs[index]->awt_cmap); } -#endif /* !HEADLESS */ } /* @@ -1067,7 +1007,6 @@ JNIEXPORT void JNICALL Java_sun_awt_X11GraphicsDevice_resetNativeData (JNIEnv *env, jclass x11gd, jint screen) { -#ifndef HEADLESS /* * Reset references to the various configs; the actual native config data * will be free'd later by the Disposer mechanism when the Java-level @@ -1081,7 +1020,6 @@ Java_sun_awt_X11GraphicsDevice_resetNativeData } x11Screens[screen].defaultConfig = NULL; x11Screens[screen].numConfigs = 0; -#endif /* !HEADLESS */ } /* @@ -1093,7 +1031,6 @@ JNIEXPORT void JNICALL Java_sun_awt_X11GraphicsConfig_dispose (JNIEnv *env, jclass x11gc, jlong configData) { -#ifndef HEADLESS AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr) jlong_to_ptr(configData); @@ -1135,7 +1072,6 @@ Java_sun_awt_X11GraphicsConfig_dispose } free(aData); -#endif /* !HEADLESS */ } /* @@ -1147,12 +1083,8 @@ JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsConfig_getXResolution( JNIEnv *env, jobject this, jint screen) { -#ifdef HEADLESS - return (jdouble)0; -#else return ((DisplayWidth(awt_display, screen) * 25.4) / DisplayWidthMM(awt_display, screen)); -#endif /* !HEADLESS */ } /* @@ -1164,12 +1096,8 @@ JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsConfig_getYResolution( JNIEnv *env, jobject this, jint screen) { -#ifdef HEADLESS - return (jdouble)0; -#else return ((DisplayHeight(awt_display, screen) * 25.4) / DisplayHeightMM(awt_display, screen)); -#endif /* !HEADLESS */ } @@ -1182,16 +1110,12 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11GraphicsConfig_getNumColors( JNIEnv *env, jobject this) { -#ifdef HEADLESS - return (jint)0; -#else AwtGraphicsConfigData *adata; adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData); return adata->awt_num_colors; -#endif /* !HEADLESS */ } /* @@ -1203,7 +1127,6 @@ JNIEXPORT void JNICALL Java_sun_awt_X11GraphicsConfig_init( JNIEnv *env, jobject this, jint visualNum, jint screen) { -#ifndef HEADLESS AwtGraphicsConfigData *adata = NULL; AwtScreenData asd = x11Screens[screen]; int i, n; @@ -1244,11 +1167,8 @@ JNIEnv *env, jobject this, jint visualNum, jint screen) (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel, (jint)tempImage->bits_per_pixel); XDestroyImage(tempImage); -#endif /* !HEADLESS */ } - - /* * Class: sun_awt_X11GraphicsConfig * Method: makeColorModel @@ -1258,9 +1178,6 @@ JNIEXPORT jobject JNICALL Java_sun_awt_X11GraphicsConfig_makeColorModel( JNIEnv *env, jobject this) { -#ifdef HEADLESS - return NULL; -#else AwtGraphicsConfigData *adata; jobject colorModel; @@ -1289,7 +1206,6 @@ JNIEnv *env, jobject this) AWT_UNLOCK (); return colorModel; -#endif /* !HEADLESS */ } @@ -1301,9 +1217,6 @@ JNIEnv *env, jobject this) JNIEXPORT jobject JNICALL Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen) { -#ifdef HEADLESS - return NULL; -#else jclass clazz; jmethodID mid; jobject bounds = NULL; @@ -1362,7 +1275,6 @@ Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen } } return bounds; -#endif /* !HEADLESS */ } /* @@ -1438,15 +1350,11 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable (JNIEnv *env, jobject this, jlong configData) { -#ifdef HEADLESS - return JNI_FALSE; -#else AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData); if (aData == NULL) { return JNI_FALSE; } return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE; -#endif } /* @@ -1457,9 +1365,6 @@ Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this) { -#ifdef HEADLESS - return JNI_FALSE; -#else int opcode = 0, firstEvent = 0, firstError = 0; jboolean ret; @@ -1468,7 +1373,6 @@ Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this) &opcode, &firstEvent, &firstError); AWT_FLUSH_UNLOCK(); return ret; -#endif /* !HEADLESS */ } /* @@ -1480,7 +1384,6 @@ JNIEXPORT void JNICALL Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env, jobject this, jint screen) { -#ifndef HEADLESS jclass clazz; jmethodID midAddVisual; Window rootWindow; @@ -1515,7 +1418,6 @@ Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env, break; } } -#endif /* !HEADLESS */ } /* @@ -1527,19 +1429,13 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env, jobject this) { -#ifdef HEADLESS - return JNI_FALSE; -#else return usingXinerama ? JNI_TRUE : JNI_FALSE; -#endif /* HEADLESS */ } /** * Begin DisplayMode/FullScreen support */ -#ifndef HEADLESS - #ifndef NO_XRANDR #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI @@ -1777,7 +1673,6 @@ X11GD_SetFullscreenMode(Window win, jboolean enabled) &event); XSync(awt_display, False); } -#endif /* !HEADLESS */ /* * Class: sun_awt_X11GraphicsDevice @@ -1788,7 +1683,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsDevice_initXrandrExtension (JNIEnv *env, jclass x11gd) { -#if defined(HEADLESS) || defined(NO_XRANDR) +#if defined(NO_XRANDR) return JNI_FALSE; #else int opcode = 0, firstEvent = 0, firstError = 0; @@ -1803,7 +1698,7 @@ Java_sun_awt_X11GraphicsDevice_initXrandrExtension AWT_FLUSH_UNLOCK(); return ret; -#endif /* HEADLESS */ +#endif /* NO_XRANDR */ } /* @@ -1815,7 +1710,7 @@ JNIEXPORT jobject JNICALL Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode (JNIEnv* env, jclass x11gd, jint screen) { -#if defined(HEADLESS) || defined(NO_XRANDR) +#if defined(NO_XRANDR) return NULL; #else XRRScreenConfiguration *config; @@ -1898,7 +1793,7 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode AWT_FLUSH_UNLOCK(); return displayMode; -#endif /* HEADLESS */ +#endif /* NO_XRANDR */ } /* @@ -1911,7 +1806,7 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes (JNIEnv* env, jclass x11gd, jint screen, jobject arrayList) { -#if !defined(HEADLESS) && !defined(NO_XRANDR) +#if !defined(NO_XRANDR) AWT_LOCK(); @@ -1986,7 +1881,7 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes } AWT_FLUSH_UNLOCK(); -#endif /* !HEADLESS */ +#endif /* !NO_XRANDR */ } /* @@ -1999,7 +1894,7 @@ Java_sun_awt_X11GraphicsDevice_configDisplayMode (JNIEnv* env, jclass x11gd, jint screen, jint width, jint height, jint refreshRate) { -#if !defined(HEADLESS) && !defined(NO_XRANDR) +#if !defined(NO_XRANDR) jboolean success = JNI_FALSE; XRRScreenConfiguration *config; Drawable root; @@ -2069,7 +1964,7 @@ Java_sun_awt_X11GraphicsDevice_configDisplayMode if (!success && !(*env)->ExceptionCheck(env)) { JNU_ThrowInternalError(env, "Could not set display mode"); } -#endif /* !HEADLESS */ +#endif /* !NO_XRANDR */ } /* @@ -2082,14 +1977,12 @@ Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive (JNIEnv* env, jclass x11gd, jlong window) { -#ifndef HEADLESS Window win = (Window)window; AWT_LOCK(); XSync(awt_display, False); /* ensures window is visible first */ X11GD_SetFullscreenMode(win, JNI_TRUE); AWT_UNLOCK(); -#endif /* !HEADLESS */ } /* @@ -2102,13 +1995,11 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive (JNIEnv* env, jclass x11gd, jlong window) { -#ifndef HEADLESS Window win = (Window)window; AWT_LOCK(); X11GD_SetFullscreenMode(win, JNI_FALSE); AWT_UNLOCK(); -#endif /* !HEADLESS */ } /** diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_Insets.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_Insets.c index cc4c68cddff..1e8d409ede0 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_Insets.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_Insets.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "java_awt_Insets.h" JNIEXPORT void JNICALL diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_MenuComponent.h b/src/java.desktop/unix/native/libawt_xawt/awt/awt_MenuComponent.h index f254e0cc195..19dd1f590cb 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_MenuComponent.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_MenuComponent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "jni_util.h" struct MenuComponentIDs { diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c index 62b13da078c..0387ee2af6f 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include @@ -32,11 +36,8 @@ #include #include "sun_awt_UNIXToolkit.h" -#ifndef HEADLESS #include "awt.h" #include "gtk_interface.h" -#endif /* !HEADLESS */ - static jclass this_class = NULL; static jmethodID icon_upcall_method = NULL; @@ -49,11 +50,7 @@ static jmethodID icon_upcall_method = NULL; */ JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) { -#ifndef HEADLESS return (jboolean)gtk_check_version(version); -#else - return JNI_FALSE; -#endif /* !HEADLESS */ } @@ -65,11 +62,7 @@ Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) { JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version, jboolean verbose) { -#ifndef HEADLESS return (jboolean)gtk_load(env, version, verbose); -#else - return JNI_FALSE; -#endif /* !HEADLESS */ } @@ -81,11 +74,7 @@ Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version, JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass) { -#ifndef HEADLESS return (jboolean)gtk->unload(); -#else - return JNI_FALSE; -#endif /* !HEADLESS */ } jboolean init_method(JNIEnv *env, jobject this) @@ -111,7 +100,6 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this, jstring filename) { -#ifndef HEADLESS int len; jsize jlen; char *filename_str = NULL; @@ -142,9 +130,6 @@ Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this, free(filename_str); return result; -#else /* HEADLESS */ - return JNI_FALSE; -#endif /* !HEADLESS */ } /* @@ -159,7 +144,6 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, jint widget_type, jstring stock_id, jint icon_size, jint text_direction, jstring detail) { -#ifndef HEADLESS int len; jsize jlen; char *stock_id_str = NULL; @@ -206,9 +190,6 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, free(detail_str); return result; -#else /* HEADLESS */ - return JNI_FALSE; -#endif /* !HEADLESS */ } /* @@ -219,11 +200,9 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, JNIEXPORT void JNICALL Java_sun_awt_UNIXToolkit_nativeSync(JNIEnv *env, jobject this) { -#ifndef HEADLESS AWT_LOCK(); XSync(awt_display, False); AWT_UNLOCK(); -#endif /* !HEADLESS */ } /* @@ -275,9 +254,5 @@ Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass) { -#ifndef HEADLESS return gtk ? gtk->version : GTK_ANY; -#else - return GTK_ANY; -#endif /* !HEADLESS */ } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/canvas.h b/src/java.desktop/unix/native/libawt_xawt/awt/canvas.h index f35decb65dd..919d880ee2b 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/canvas.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/canvas.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,11 +22,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef _CANVAS_H_ #define _CANVAS_H_ -#ifndef HEADLESS KeySym awt_getX11KeySym(jint awtKey); -#endif /* !HEADLESS */ #endif /* _CANVAS_H_ */ diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index 4995044dc49..6fe9797ecd3 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h index 18e53496899..d786117ce78 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef _GTK2_INTERFACE_H #define _GTK2_INTERFACE_H diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index 886437e2a79..2d92f85ec5c 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h index 8b461ff335e..51fd7778484 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef _GTK3_INTERFACE_H #define _GTK3_INTERFACE_H diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c index 0b78024b434..c8573ed3fbf 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include "jvm_md.h" diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h index a2021ff02b7..98097e18301 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef _GTK_INTERFACE_H #define _GTK_INTERFACE_H diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/list.c b/src/java.desktop/unix/native/libawt_xawt/awt/list.c index abbfe7c72c0..fc3e02103b3 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/list.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/list.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,10 @@ from The Open Group. ----------------------------------------------------------------------- **/ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/list.h b/src/java.desktop/unix/native/libawt_xawt/awt/list.h index ff538ccfe07..bbae6d319ed 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/list.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,10 @@ from The Open Group. -------------------------------------------------------------------- **/ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef LIST_DEF #define LIST_DEF diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c index 7f89010715a..e2e3cd11809 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,10 @@ from The Open Group. ------------------------------------------------------------------------ **/ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.h b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.h index a505cd1a457..9c8149ae3fc 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,10 @@ from The Open Group. ------------------------------------------------------------------------ **/ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + extern int GetMultiVisualRegions( Display *, Window, int, int, unsigned int, unsigned int, int *, int *, XVisualInfo **, int *, diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c b/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c index 556fe252538..0700f545eb1 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c index ef52c7aaf25..7bfd0d8b860 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "gtk_interface.h" #include "com_sun_java_swing_plaf_gtk_GTKEngine.h" #include diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c index a977f6bee2e..5b39fbd571d 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include "gtk_interface.h" diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/wsutils.h b/src/java.desktop/unix/native/libawt_xawt/awt/wsutils.h index 52666a26bef..0daa569f527 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/wsutils.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/wsutils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,6 +70,10 @@ from The Open Group. * ******************************************************************************/ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + typedef unsigned long Pixel; /* This is the actual structure returned by the X server describing the diff --git a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c index bd6023d89b8..4709f8bb399 100644 --- a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c +++ b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "X11SurfaceData.h" #include #include @@ -249,7 +253,6 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsEnvironment_initXRender (JNIEnv *env, jclass x11ge, jboolean verbose, jboolean ignoreLinuxVersion) { -#ifndef HEADLESS static jboolean xrenderAvailable = JNI_FALSE; static jboolean firstTime = JNI_TRUE; @@ -267,9 +270,6 @@ Java_sun_awt_X11GraphicsEnvironment_initXRender firstTime = JNI_FALSE; } return xrenderAvailable; -#else - return JNI_FALSE; -#endif /* !HEADLESS */ } diff --git a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRSurfaceData.c b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRSurfaceData.c index 60b4d5b71e3..53068bd19d4 100644 --- a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRSurfaceData.c +++ b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "GraphicsPrimitiveMgr.h" #include "Region.h" #include "Trace.h" @@ -43,20 +47,16 @@ #include #include -#ifndef HEADLESS jfieldID pictID; jfieldID xidID; jfieldID blitMaskPMID; jfieldID blitMaskPictID; -#endif /* !HEADLESS */ JNIEXPORT void JNICALL Java_sun_java2d_xr_XRSurfaceData_initXRPicture(JNIEnv *env, jobject xsd, jlong pXSData, jint pictFormat) { -#ifndef HEADLESS - X11SDOps *xsdo; XRenderPictFormat *fmt; @@ -78,13 +78,11 @@ JNIEXPORT void JNICALL (*env)->SetIntField (env, xsd, pictID, xsdo->xrPic); (*env)->SetIntField (env, xsd, xidID, xsdo->drawable); -#endif /* !HEADLESS */ } JNIEXPORT void JNICALL Java_sun_java2d_xr_XRSurfaceData_initIDs(JNIEnv *env, jclass xsd) { -#ifndef HEADLESS J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initIDs"); pictID = (*env)->GetFieldID(env, xsd, "picture", "I"); @@ -97,7 +95,6 @@ Java_sun_java2d_xr_XRSurfaceData_initIDs(JNIEnv *env, jclass xsd) } XShared_initIDs(env, JNI_FALSE); -#endif /* !HEADLESS */ } @@ -107,7 +104,6 @@ Java_sun_java2d_xr_XRSurfaceData_XRInitSurface(JNIEnv *env, jclass xsd, jint width, jint height, jlong drawable, jint pictFormat) { -#ifndef HEADLESS X11SDOps *xsdo; J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initSurface"); @@ -118,7 +114,6 @@ Java_sun_java2d_xr_XRSurfaceData_XRInitSurface(JNIEnv *env, jclass xsd, } XShared_initSurface(env, xsdo, depth, width, height, drawable); -#endif /* !HEADLESS */ } @@ -127,7 +122,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_xr_XRSurfaceData_freeXSDOPicture(JNIEnv *env, jobject xsd, jlong pXSData) { -#ifndef HEADLESS X11SDOps *xsdo; J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_freeXSDOPicture"); @@ -141,5 +135,4 @@ Java_sun_java2d_xr_XRSurfaceData_freeXSDOPicture(JNIEnv *env, jobject xsd, XRenderFreePicture(awt_display, xsdo->xrPic); xsdo->xrPic = None; } -#endif /* !HEADLESS */ } diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c b/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c index 102c42ca5b2..ac8d1fc154b 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include #include @@ -70,12 +74,9 @@ struct ComponentIDs componentIDs; struct MenuComponentIDs menuComponentIDs; -#ifndef HEADLESS - extern Display* awt_init_Display(JNIEnv *env, jobject this); extern void freeNativeStringArray(char **array, jsize length); extern char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length); -#endif /* !HEADLESS */ /* This function gets called from the static initializer for FileDialog.java to initialize the fieldIDs for fields that may be accessed from C */ @@ -300,11 +301,7 @@ Java_java_awt_TextField_initIDs } JNIEXPORT jboolean JNICALL AWTIsHeadless() { -#ifdef HEADLESS - return JNI_TRUE; -#else return JNI_FALSE; -#endif } JNIEXPORT void JNICALL Java_java_awt_Dialog_initIDs (JNIEnv *env, jclass cls) diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c b/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c index 461d0a44f55..be4b692b043 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c @@ -86,7 +86,6 @@ jfieldID graphicsConfigID; extern jobject currentX11InputMethodInstance; extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *); Boolean awt_UseType4Patch = False; -/* how about HEADLESS */ Boolean awt_ServerDetected = False; Boolean awt_XKBDetected = False; Boolean awt_IsXsun = False; 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 fba687ec120..19173eb6052 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, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "awt.h" #include "awt_util.h" #include "jni.h" diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c index 96acfb59d11..1e0b67316ae 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "jni_util.h" #include "gtk_interface.h" #include "gnome_interface.h" diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c index 9b415476f83..b5f267b9cf3 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include #include "jvm_md.h" #include diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h index 0a574615d10..ec62bd452b6 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef AWT_TASKBAR_H #define AWT_TASKBAR_H diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.c b/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.c index 46c96e13680..76d6ed4dd81 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #include "gnome_interface.h" GNOME_URL_SHOW_TYPE *gnome_url_show = NULL; diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h b/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h index 86ea796ba7e..422e3a08f70 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ * questions. */ +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + #ifndef _GNOME_INTERFACE_H #define _GNOME_INTERFACE_H #include "gtk_interface.h" diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp index 12f47a2e732..2aadcd5a08c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,7 @@ jobject AwtClipboard::theCurrentClipboard; BOOL AwtClipboard::isGettingOwnership = FALSE; volatile jmethodID AwtClipboard::handleContentsChangedMID; -volatile BOOL AwtClipboard::skipInitialWmDrawClipboardMsg = TRUE; volatile BOOL AwtClipboard::isClipboardViewerRegistered = FALSE; -volatile HWND AwtClipboard::hwndNextViewer = NULL; #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) @@ -59,27 +57,11 @@ void AwtClipboard::LostOwnership(JNIEnv *env) { } } -void AwtClipboard::WmChangeCbChain(WPARAM wParam, LPARAM lParam) { - if ((HWND)wParam == hwndNextViewer) { - hwndNextViewer = (HWND)lParam; - } else if (hwndNextViewer != NULL) { - ::SendMessage(hwndNextViewer, WM_CHANGECBCHAIN, wParam, lParam); - } -} - -void AwtClipboard::WmDrawClipboard(JNIEnv *env, WPARAM wParam, LPARAM lParam) { - if (skipInitialWmDrawClipboardMsg) { - // skipping the first contents change notification as it comes - // immediately after registering the clipboard viewer window - // and it is not caused by an actual contents change. - skipInitialWmDrawClipboardMsg = FALSE; - return; - } +void AwtClipboard::WmClipboardUpdate(JNIEnv *env) { if (theCurrentClipboard != NULL) { env->CallVoidMethod(theCurrentClipboard, handleContentsChangedMID); DASSERT(!safe_ExceptionOccurred(env)); } - ::SendMessage(hwndNextViewer, WM_DRAWCLIPBOARD, wParam, lParam); } void AwtClipboard::RegisterClipboardViewer(JNIEnv *env, jobject jclipboard) { @@ -96,7 +78,7 @@ void AwtClipboard::RegisterClipboardViewer(JNIEnv *env, jobject jclipboard) { env->GetMethodID(cls, "handleContentsChanged", "()V"); DASSERT(AwtClipboard::handleContentsChangedMID != NULL); - hwndNextViewer = ::SetClipboardViewer(AwtToolkit::GetInstance().GetHWnd()); + ::AddClipboardFormatListener(AwtToolkit::GetInstance().GetHWnd()); isClipboardViewerRegistered = TRUE; } @@ -104,10 +86,8 @@ void AwtClipboard::UnregisterClipboardViewer(JNIEnv *env) { TRY; if (isClipboardViewerRegistered) { - ::ChangeClipboardChain(AwtToolkit::GetInstance().GetHWnd(), AwtClipboard::hwndNextViewer); - AwtClipboard::hwndNextViewer = NULL; + ::RemoveClipboardFormatListener(AwtToolkit::GetInstance().GetHWnd()); isClipboardViewerRegistered = FALSE; - skipInitialWmDrawClipboardMsg = TRUE; } CATCH_BAD_ALLOC; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h index a9e9d71d544..7821dacdb74 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,7 @@ class AwtClipboard { private: static BOOL isGettingOwnership; - // handle to the next window in the clipboard viewer chain - static volatile HWND hwndNextViewer; static volatile BOOL isClipboardViewerRegistered; - static volatile BOOL skipInitialWmDrawClipboardMsg; static volatile jmethodID handleContentsChangedMID; public: @@ -57,8 +54,7 @@ class AwtClipboard { } static void LostOwnership(JNIEnv *env); - static void WmChangeCbChain(WPARAM wparam, LPARAM lparam); - static void WmDrawClipboard(JNIEnv *env, WPARAM wparam, LPARAM lparam); + static void WmClipboardUpdate(JNIEnv *env); static void RegisterClipboardViewer(JNIEnv *env, jobject jclipboard); static void UnregisterClipboardViewer(JNIEnv *env); }; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 7a7148d888d..1ab9c6f6278 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -1067,12 +1067,8 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message, AwtClipboard::LostOwnership((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); return 0; } - case WM_CHANGECBCHAIN: { - AwtClipboard::WmChangeCbChain(wParam, lParam); - return 0; - } - case WM_DRAWCLIPBOARD: { - AwtClipboard::WmDrawClipboard((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), wParam, lParam); + case WM_CLIPBOARDUPDATE: { + AwtClipboard::WmClipboardUpdate((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); return 0; } case WM_AWT_LIST_SETMULTISELECT: { diff --git a/src/java.logging/share/classes/java/util/logging/LogRecord.java b/src/java.logging/share/classes/java/util/logging/LogRecord.java index af602a2947d..d628d7ffbe1 100644 --- a/src/java.logging/share/classes/java/util/logging/LogRecord.java +++ b/src/java.logging/share/classes/java/util/logging/LogRecord.java @@ -72,7 +72,7 @@ public class LogRecord implements java.io.Serializable { private static final AtomicLong globalSequenceNumber - = new AtomicLong(0); + = new AtomicLong(); /** * Logging message level diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java b/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java index e85b92786f6..cc529208a87 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java @@ -39,7 +39,7 @@ abstract class WindowUpdateSender { final int limit; final Http2Connection connection; - final AtomicInteger received = new AtomicInteger(0); + final AtomicInteger received = new AtomicInteger(); WindowUpdateSender(Http2Connection connection) { this(connection, connection.clientSettings.getParameter(SettingsFrame.INITIAL_WINDOW_SIZE)); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java index f81b454181d..573ac85899d 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java @@ -375,7 +375,7 @@ void stop() { scheduler.stop(); } - AtomicInteger count = new AtomicInteger(0); + AtomicInteger count = new AtomicInteger(); // minimum number of bytes required to call unwrap. // Usually this is 0, unless there was a buffer underflow. diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java index f45c4a06352..f9c098a05d5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java @@ -74,7 +74,7 @@ public enum SchedulingAction { CONTINUE, RETURN, RESCHEDULE } private final CompletableFuture cf; private final SequentialScheduler pushScheduler; private final AtomicReference errorRef = new AtomicReference<>(); - final AtomicLong upstreamWindow = new AtomicLong(0); + final AtomicLong upstreamWindow = new AtomicLong(); /** * Wraps the given downstream subscriber. For each call to {@link diff --git a/src/java.rmi/share/classes/java/rmi/server/ObjID.java b/src/java.rmi/share/classes/java/rmi/server/ObjID.java index 9cd1ff57c46..86179c2ba0f 100644 --- a/src/java.rmi/share/classes/java/rmi/server/ObjID.java +++ b/src/java.rmi/share/classes/java/rmi/server/ObjID.java @@ -84,7 +84,7 @@ public final class ObjID implements Serializable { /** indicate compatibility with JDK 1.1.x version of class */ private static final long serialVersionUID = -6386392263968365220L; - private static final AtomicLong nextObjNum = new AtomicLong(0); + private static final AtomicLong nextObjNum = new AtomicLong(); private static final UID mySpace = new UID(); private static final SecureRandom secureRandom = new SecureRandom(); diff --git a/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java b/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java index 1eca061def1..98e7df3c90c 100644 --- a/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java +++ b/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java @@ -30,7 +30,6 @@ import java.security.PrivilegedAction; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -70,7 +69,7 @@ private RuntimeUtil() { scheduler = new ScheduledThreadPoolExecutor( schedulerThreads, new ThreadFactory() { - private final AtomicInteger count = new AtomicInteger(0); + private final AtomicInteger count = new AtomicInteger(); public Thread newThread(Runnable runnable) { try { return AccessController.doPrivileged( diff --git a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java index 06980f17c08..c946ff5be3d 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java +++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java @@ -128,8 +128,6 @@ public class UnicastServerRef extends UnicastRef private static final Map,?> withoutSkeletons = Collections.synchronizedMap(new WeakHashMap,Void>()); - private final AtomicInteger methodCallIDCount = new AtomicInteger(0); - /** * Create a new (empty) Unicast server remote reference. * The filter is null to defer to the default ObjectInputStream filter, if any. diff --git a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index dd15491f1e3..780943128d6 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -115,7 +115,7 @@ public Thread newThread(Runnable runnable) { }); /** total connections handled */ - private static final AtomicInteger connectionCount = new AtomicInteger(0); + private static final AtomicInteger connectionCount = new AtomicInteger(); /** client host for the current thread's connection */ private static final ThreadLocal diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java index b3215244f2c..1f7d0c92daf 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java @@ -664,19 +664,9 @@ public enum Kind { PROVIDES(ProvidesTree.class), /** - * {@preview Associated with records, a preview feature of the Java language. - * - * This enum constant is associated with records, a preview - * feature of the Java language. Preview features - * may be removed in a future release, or upgraded to permanent - * features of the Java language.} - * * Used for instances of {@link ClassTree} representing records. - * - * @since 14 + * @since 16 */ - @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, - essentialAPI=false) RECORD(ClassTree.class), /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index cf760027c67..4f992a31ae3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -168,7 +168,6 @@ public boolean isPreview(Feature feature) { if (feature == Feature.PATTERN_MATCHING_IN_INSTANCEOF || feature == Feature.DECONSTRUCTION_PATTERNS || feature == Feature.REIFIABLE_TYPES_INSTANCEOF || - feature == Feature.RECORDS || feature == Feature.SEALED_CLASSES) return true; //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing). diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index b36be9387af..5ab1a704caf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2038,7 +2038,10 @@ Type condType(List positions, List condTypes) { // both are known to be reference types. The result is // lub(thentype,elsetype). This cannot fail, as it will // always be possible to infer "Object" if nothing better. - return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector())); + return types.lub(condTypes.stream() + .map(t -> t.baseType()) + .filter(t -> !t.hasTag(BOT)) + .collect(List.collector())); } final static TypeTag[] primitiveTags = new TypeTag[]{ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index b59065c5511..2c8dc675450 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -159,8 +159,7 @@ protected Check(Context context) { deferredLintHandler = DeferredLintHandler.instance(context); - allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) && - Feature.RECORDS.allowedInSource(source); + allowRecords = Feature.RECORDS.allowedInSource(source); allowSealed = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) && Feature.SEALED_CLASSES.allowedInSource(source); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 562e8ab8071..727d2989adf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -150,8 +150,7 @@ protected Resolve(Context context) { Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source); polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); allowModules = Feature.MODULES.allowedInSource(source); - allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) && - Feature.RECORDS.allowedInSource(source); + allowRecords = Feature.RECORDS.allowedInSource(source); } /** error symbols, which are returned when resolution fails diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index a0085a3e6e1..4528d0de44d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -272,8 +272,7 @@ protected ClassReader(Context context) { Source source = Source.instance(context); preview = Preview.instance(context); allowModules = Feature.MODULES.allowedInSource(source); - allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) && - Feature.RECORDS.allowedInSource(source); + allowRecords = Feature.RECORDS.allowedInSource(source); allowSealedTypes = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) && Feature.SEALED_CLASSES.allowedInSource(source); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 62520fbc186..5c74dd499ab 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -184,8 +184,7 @@ protected JavacParser(ParserFactory fac, endPosTable = newEndPosTable(keepEndPositions); this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) && Feature.SWITCH_EXPRESSION.allowedInSource(source); - this.allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) && - Feature.RECORDS.allowedInSource(source); + this.allowRecords = Feature.RECORDS.allowedInSource(source); this.allowSealedTypes = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) && Feature.SEALED_CLASSES.allowedInSource(source); } @@ -3807,7 +3806,7 @@ protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods } else { int pos = token.pos; List errs; - if (token.kind == IDENTIFIER && token.name() == names.record && preview.isEnabled()) { + if (token.kind == IDENTIFIER && token.name() == names.record) { checkSourceLevel(Feature.RECORDS); JCErroneous erroneousTree = syntaxError(token.pos, List.of(mods), Errors.RecordHeaderExpected); return toP(F.Exec(erroneousTree)); @@ -4304,7 +4303,7 @@ protected boolean isRecordStart() { (peekToken(TokenKind.IDENTIFIER, TokenKind.LPAREN) || peekToken(TokenKind.IDENTIFIER, TokenKind.EOF) || peekToken(TokenKind.IDENTIFIER, TokenKind.LT))) { - checkSourceLevel(Feature.RECORDS); + checkSourceLevel(Feature.RECORDS); return true; } else { return false; diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java index 5d67234180a..622d93dab35 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java @@ -79,17 +79,24 @@ final public boolean validate(Map params) } } - withFindNeededPackages = LibProvidersLookup.supported(); - if (!withFindNeededPackages) { - final String advice; - if ("deb".equals(getID())) { - advice = "message.deb-ldd-not-available.advice"; - } else { - advice = "message.rpm-ldd-not-available.advice"; + if (!isDefault()) { + withFindNeededPackages = false; + Log.verbose(MessageFormat.format(I18N.getString( + "message.not-default-bundler-no-dependencies-lookup"), + getName())); + } else { + withFindNeededPackages = LibProvidersLookup.supported(); + if (!withFindNeededPackages) { + final String advice; + if ("deb".equals(getID())) { + advice = "message.deb-ldd-not-available.advice"; + } else { + advice = "message.rpm-ldd-not-available.advice"; + } + // Let user know package dependencies will not be generated. + Log.error(String.format("%s\n%s", I18N.getString( + "message.ldd-not-available"), I18N.getString(advice))); } - // Let user know package dependencies will not be generated. - Log.error(String.format("%s\n%s", I18N.getString( - "message.ldd-not-available"), I18N.getString(advice))); } // Packaging specific validation @@ -192,7 +199,6 @@ private List getListOfNeededPackages( neededLibPackages = Collections.emptyList(); if (!Files.exists(thePackage.sourceRoot())) { Log.info(I18N.getString("warning.foreign-app-image")); - } } diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties index 0474234e171..4c4d2ac7bf4 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties @@ -62,6 +62,7 @@ message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd. message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd. warning.foreign-app-image=Warning: app-image dir not generated by jpackage. +message.not-default-bundler-no-dependencies-lookup={0} is not the default package type. Package dependencies will not be generated. error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties index 48a0f3438a9..03e66e1ad26 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties @@ -40,8 +40,6 @@ resource.menu-shortcut-descriptor=\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30 resource.menu-icon=\u30E1\u30CB\u30E5\u30FC\u30FB\u30A2\u30A4\u30B3\u30F3 resource.rpm-spec-file=RPM\u4ED5\u69D8\u30D5\u30A1\u30A4\u30EB -warning.foreign-app-image=Warning: app-image dir not generated by jpackage. - error.tool-not-found.advice=\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044 error.tool-old-version.advice=\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044 @@ -63,6 +61,9 @@ message.ldd-not-available=ldd\u30B3\u30DE\u30F3\u30C9\u304C\u898B\u3064\u304B\u3 message.deb-ldd-not-available.advice="libc-bin" DEB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066ldd\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002 message.rpm-ldd-not-available.advice="glibc-common" RPM\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066ldd\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002 +warning.foreign-app-image=Warning: app-image dir not generated by jpackage. +message.not-default-bundler-no-dependencies-lookup={0} is not the default package type. Package dependencies will not be generated. + error.unexpected-package-property="{0}"\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u5FC5\u8981\u306A\u5024\u306F[{1}]\u3067\u3059\u3002\u51FA\u529B\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u5B9F\u969B\u306E\u5024\u306F[{2}]\u3067\u3059\u3002\u30EA\u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30AB\u30B9\u30BF\u30E0"{3}"\u30D5\u30A1\u30A4\u30EB\u306B\u306F\u3001"{0}"\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u30CF\u30FC\u30C9\u30B3\u30FC\u30C9\u3055\u308C\u305F\u5024\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u3088\u3046\u3067\u3059 error.unexpected-package-property.advice=\u30AB\u30B9\u30BF\u30E0"{3}"\u30D5\u30A1\u30A4\u30EB\u3067{2}\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u30CF\u30FC\u30C9\u30B3\u30FC\u30C9\u3055\u308C\u305F\u5024[{1}]\u3067\u306F\u306A\u304F\u3001[{0}]\u30D1\u30BF\u30FC\u30F3\u6587\u5B57\u5217\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044 error.unexpected-default-package-property.advice=\u30AB\u30B9\u30BF\u30E0"{1}"\u30D5\u30A1\u30A4\u30EB\u3067{0}\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u5024\u3092\u660E\u793A\u7684\u306B\u8A2D\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044 diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties index 52feabd13f4..3c899a8c44f 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties @@ -40,8 +40,6 @@ resource.menu-shortcut-descriptor=\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u63CF\u8F resource.menu-icon=\u83DC\u5355\u56FE\u6807 resource.rpm-spec-file=RPM \u89C4\u8303\u6587\u4EF6 -warning.foreign-app-image=Warning: app-image dir not generated by jpackage. - error.tool-not-found.advice=\u8BF7\u5B89\u88C5\u6240\u9700\u7684\u7A0B\u5E8F\u5305 error.tool-old-version.advice=\u8BF7\u5B89\u88C5\u6240\u9700\u7684\u7A0B\u5E8F\u5305 @@ -63,6 +61,9 @@ message.ldd-not-available=\u672A\u627E\u5230 ldd \u547D\u4EE4\u3002\u5C06\u4E0D\ message.deb-ldd-not-available.advice=\u5B89\u88C5 "libc-bin" DEB \u7A0B\u5E8F\u5305\u4EE5\u83B7\u53D6 ldd\u3002 message.rpm-ldd-not-available.advice=\u5B89\u88C5 "glibc-common" RPM \u7A0B\u5E8F\u5305\u4EE5\u83B7\u53D6 ldd\u3002 +warning.foreign-app-image=Warning: app-image dir not generated by jpackage. +message.not-default-bundler-no-dependencies-lookup={0} is not the default package type. Package dependencies will not be generated. + error.unexpected-package-property="{0}" \u5C5E\u6027\u7684\u9884\u671F\u503C\u4E3A [{1}]\u3002\u8F93\u51FA\u7A0B\u5E8F\u5305\u4E2D\u7684\u5B9E\u9645\u503C\u4E3A [{2}]\u3002\u4E0E\u5B9A\u5236\u7684 "{3}" \u6587\u4EF6\u76F8\u4F3C\uFF0C\u8BE5\u6587\u4EF6\u6240\u5728\u7684\u8D44\u6E90\u76EE\u5F55\u4E2D\u5305\u542B "{0}" \u5C5E\u6027\u7684\u786C\u7F16\u7801\u503C error.unexpected-package-property.advice=\u5728\u5B9A\u5236\u7684 "{3}" \u6587\u4EF6\u4E2D\u4F7F\u7528 [{0}] \u6A21\u5F0F\u5B57\u7B26\u4E32\uFF0C\u800C\u975E {2} \u5C5E\u6027\u7684\u786C\u7F16\u7801\u503C [{1}] error.unexpected-default-package-property.advice=\u8BF7\u52FF\u5728\u5B9A\u5236\u7684 "{1}" \u6587\u4EF6\u4E2D\u663E\u5F0F\u8BBE\u7F6E {0} \u5C5E\u6027\u7684\u503C diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java index 709f6f1a530..2973731010f 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java @@ -473,15 +473,6 @@ private Path buildDMG( Map params, //add license if needed if (Files.exists(getConfig_LicenseFile(params))) { - //hdiutil unflatten your_image_file.dmg - pb = new ProcessBuilder( - hdiutil, - "unflatten", - finalDMG.toAbsolutePath().toString() - ); - IOUtils.exec(pb); - - //add license pb = new ProcessBuilder( hdiutil, "udifrez", @@ -490,15 +481,6 @@ private Path buildDMG( Map params, getConfig_LicenseFile(params).toAbsolutePath().toString() ); IOUtils.exec(pb); - - //hdiutil flatten your_image_file.dmg - pb = new ProcessBuilder( - hdiutil, - "flatten", - finalDMG.toAbsolutePath().toString() - ); - IOUtils.exec(pb); - } //Delete the temporary image diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java index 93a124f44d4..3b882a67503 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java @@ -500,7 +500,7 @@ ArithmeticException divZeroException() { final AbstractVector defaultReinterpret(AbstractSpecies rsp) { int blen = Math.max(this.bitSize(), rsp.vectorBitSize()) / Byte.SIZE; - ByteOrder bo = ByteOrder.LITTLE_ENDIAN; + ByteOrder bo = ByteOrder.nativeOrder(); ByteBuffer bb = ByteBuffer.allocate(blen); this.intoByteBuffer(bb, 0, bo); VectorMask m = rsp.maskAll(true); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java index 1d6dc27e808..05558ff3551 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java @@ -48,7 +48,7 @@ * an event stream. */ abstract class AbstractEventStream implements EventStream { - private final static AtomicLong counter = new AtomicLong(0); + private final static AtomicLong counter = new AtomicLong(); private final Object terminated = new Object(); private final Runnable flushOperation = () -> dispatcher().runFlushActions(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java index 0e0486b6ab0..08f1b567cff 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java @@ -27,8 +27,9 @@ import java.io.IOException; import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.ByteBuffer; - import jdk.jfr.events.Handlers; import jdk.jfr.internal.handlers.EventHandler; @@ -41,8 +42,6 @@ final class SocketChannelImplInstrumentor { private SocketChannelImplInstrumentor() { } - private InetSocketAddress remoteAddress; - @SuppressWarnings("deprecation") @JIInstrumentationMethod public int read(ByteBuffer dst) throws IOException { @@ -58,16 +57,28 @@ public int read(ByteBuffer dst) throws IOException { } finally { long duration = EventHandler.timestamp() - start; if (handler.shouldCommit(duration)) { - String hostString = remoteAddress.getAddress().toString(); - int delimiterIndex = hostString.lastIndexOf('/'); + SocketAddress remoteAddress = getRemoteAddress(); + if (remoteAddress instanceof InetSocketAddress) { + InetSocketAddress isa = (InetSocketAddress) remoteAddress; + String hostString = isa.getAddress().toString(); + int delimiterIndex = hostString.lastIndexOf('/'); - String host = hostString.substring(0, delimiterIndex); - String address = hostString.substring(delimiterIndex + 1); - int port = remoteAddress.getPort(); - if (bytesRead < 0) { - handler.write(start, duration, host, address, port, 0, 0L, true); + String host = hostString.substring(0, delimiterIndex); + String address = hostString.substring(delimiterIndex + 1); + int port = isa.getPort(); + if (bytesRead < 0) { + handler.write(start, duration, host, address, port, 0, 0L, true); + } else { + handler.write(start, duration, host, address, port, 0, bytesRead, false); + } } else { - handler.write(start, duration, host, address, port, 0, bytesRead, false); + UnixDomainSocketAddress udsa = (UnixDomainSocketAddress) remoteAddress; + String path = "[" + udsa.getPath().toString() + "]"; + if (bytesRead < 0) { + handler.write(start, duration, "Unix domain socket", path, 0, 0, 0L, true); + } else { + handler.write(start, duration, "Unix domain socket", path, 0, 0, bytesRead, false); + } } } } @@ -81,7 +92,6 @@ public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { if (!handler.isEnabled()) { return read(dsts, offset, length); } - long bytesRead = 0; long start = 0; try { @@ -90,16 +100,28 @@ public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { } finally { long duration = EventHandler.timestamp() - start; if (handler.shouldCommit(duration)) { - String hostString = remoteAddress.getAddress().toString(); - int delimiterIndex = hostString.lastIndexOf('/'); + SocketAddress remoteAddress = getRemoteAddress(); + if (remoteAddress instanceof InetSocketAddress) { + InetSocketAddress isa = (InetSocketAddress) remoteAddress; + String hostString = isa.getAddress().toString(); + int delimiterIndex = hostString.lastIndexOf('/'); - String host = hostString.substring(0, delimiterIndex); - String address = hostString.substring(delimiterIndex + 1); - int port = remoteAddress.getPort(); - if (bytesRead < 0) { - handler.write(start, duration, host, address, port, 0, 0L, true); + String host = hostString.substring(0, delimiterIndex); + String address = hostString.substring(delimiterIndex + 1); + int port = isa.getPort(); + if (bytesRead < 0) { + handler.write(start, duration, host, address, port, 0, 0L, true); + } else { + handler.write(start, duration, host, address, port, 0, bytesRead, false); + } } else { - handler.write(start, duration, host, address, port, 0, bytesRead, false); + UnixDomainSocketAddress udsa = (UnixDomainSocketAddress) remoteAddress; + String path = "[" + udsa.getPath().toString() + "]"; + if (bytesRead < 0) { + handler.write(start, duration, "Unix domain socket", path, 0, 0, 0L, true); + } else { + handler.write(start, duration, "Unix domain socket", path, 0, 0, bytesRead, false); + } } } } @@ -121,19 +143,32 @@ public int write(ByteBuffer buf) throws IOException { } finally { long duration = EventHandler.timestamp() - start; if (handler.shouldCommit(duration)) { - String hostString = remoteAddress.getAddress().toString(); - int delimiterIndex = hostString.lastIndexOf('/'); - - String host = hostString.substring(0, delimiterIndex); - String address = hostString.substring(delimiterIndex + 1); - int port = remoteAddress.getPort(); long bytes = bytesWritten < 0 ? 0 : bytesWritten; - handler.write(start, duration, host, address, port, bytes); + SocketAddress remoteAddress = getRemoteAddress(); + if (remoteAddress instanceof InetSocketAddress) { + InetSocketAddress isa = (InetSocketAddress) remoteAddress; + String hostString = isa.getAddress().toString(); + int delimiterIndex = hostString.lastIndexOf('/'); + + String host = hostString.substring(0, delimiterIndex); + String address = hostString.substring(delimiterIndex + 1); + int port = isa.getPort(); + handler.write(start, duration, host, address, port, bytes); + } else { + UnixDomainSocketAddress udsa = (UnixDomainSocketAddress) remoteAddress; + String path = "[" + udsa.getPath().toString() + "]"; + handler.write(start, duration, "Unix domain socket", path, 0, bytes); + } } } return bytesWritten; } + public SocketAddress getRemoteAddress() throws IOException { + // gets replaced by call to instrumented class + return null; + } + @SuppressWarnings("deprecation") @JIInstrumentationMethod public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { @@ -149,14 +184,22 @@ public long write(ByteBuffer[] srcs, int offset, int length) throws IOException } finally { long duration = EventHandler.timestamp() - start; if (handler.shouldCommit(duration)) { - String hostString = remoteAddress.getAddress().toString(); - int delimiterIndex = hostString.lastIndexOf('/'); - - String host = hostString.substring(0, delimiterIndex); - String address = hostString.substring(delimiterIndex + 1); - int port = remoteAddress.getPort(); long bytes = bytesWritten < 0 ? 0 : bytesWritten; - handler.write(start, duration, host, address, port, bytes); + SocketAddress remoteAddress = getRemoteAddress(); + if (remoteAddress instanceof InetSocketAddress) { + InetSocketAddress isa = (InetSocketAddress) remoteAddress; + String hostString = isa.getAddress().toString(); + int delimiterIndex = hostString.lastIndexOf('/'); + + String host = hostString.substring(0, delimiterIndex); + String address = hostString.substring(delimiterIndex + 1); + int port = isa.getPort(); + handler.write(start, duration, host, address, port, bytes); + } else { + UnixDomainSocketAddress udsa = (UnixDomainSocketAddress) remoteAddress; + String path = "[" + udsa.getPath().toString() + "]"; + handler.write(start, duration, "Unix domain socket", path, 0, bytes); + } } } return bytesWritten; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/ThrowableTracer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/ThrowableTracer.java index 404a3fd772d..d3f03636605 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/ThrowableTracer.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/ThrowableTracer.java @@ -32,7 +32,7 @@ public final class ThrowableTracer { - private static final AtomicLong numThrowables = new AtomicLong(0); + private static final AtomicLong numThrowables = new AtomicLong(); public static void traceError(Error e, String message) { if (e instanceof OutOfMemoryError) { diff --git a/src/java.base/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 similarity index 100% rename from src/java.base/share/man/jfr.1 rename to src/jdk.jfr/share/man/jfr.1 diff --git a/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java b/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java index e0ded9dd364..aac634e6aed 100644 --- a/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java +++ b/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,12 @@ package jdk.net; import java.net.SocketException; +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.GroupPrincipal; import java.security.AccessController; import java.security.PrivilegedAction; import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; +import sun.nio.fs.UnixUserPrincipals; class LinuxSocketOptions extends PlatformSocketOptions { @@ -54,6 +57,10 @@ boolean keepAliveOptionsSupported() { return keepAliveOptionsSupported0(); } + boolean peerCredentialsSupported() { + return true; + } + @Override void setTcpkeepAliveProbes(int fd, final int value) throws SocketException { setTcpkeepAliveProbes0(fd, value); @@ -94,6 +101,16 @@ int getIncomingNapiId(int fd) throws SocketException { return getIncomingNapiId0(fd); } + @Override + UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException { + long l = getSoPeerCred0(fd); + int uid = (int)(l >> 32); + int gid = (int)l; + UserPrincipal user = UnixUserPrincipals.fromUid(uid); + GroupPrincipal group = UnixUserPrincipals.fromGid(gid); + return new UnixDomainPrincipal(user, group); + } + private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; @@ -102,6 +119,7 @@ int getIncomingNapiId(int fd) throws SocketException { private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; private static native void setQuickAck0(int fd, boolean on) throws SocketException; private static native boolean getQuickAck0(int fd) throws SocketException; + private static native long getSoPeerCred0(int fd) throws SocketException; private static native boolean keepAliveOptionsSupported0(); private static native boolean quickAckSupported0(); private static native boolean incomingNapiIdSupported0(); diff --git a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c index 369fe6b3130..a10d9418e9d 100644 --- a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c +++ b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c @@ -23,6 +23,8 @@ * questions. */ #include +#include +#include #include #include #include @@ -109,6 +111,29 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_quickAckSupported0 return socketOptionSupported(SOL_SOCKET, TCP_QUICKACK); } +/* + * Class: jdk_net_LinuxSocketOptions + * Method: getSoPeerCred0 + * Signature: (I)L + */ +JNIEXPORT jlong JNICALL Java_jdk_net_LinuxSocketOptions_getSoPeerCred0 + (JNIEnv *env, jclass clazz, jint fd) { + + int rv; + struct ucred cred; + socklen_t len = sizeof(cred); + + if ((rv=getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) < 0) { + handleError(env, rv, "get SO_PEERCRED failed"); + } else { + if ((int)cred.uid == -1) { + handleError(env, -1, "get SO_PEERCRED failed"); + cred.uid = cred.gid = -1; + } + } + return (((jlong)cred.uid) << 32) | (cred.gid & 0xffffffffL); +} + /* * Class: jdk_net_LinuxSocketOptions * Method: keepAliveOptionsSupported0 diff --git a/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java b/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java index 065a233629b..88274d1b27e 100644 --- a/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java +++ b/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,12 @@ package jdk.net; import java.net.SocketException; +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.GroupPrincipal; import java.security.AccessController; import java.security.PrivilegedAction; import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; +import sun.nio.fs.UnixUserPrincipals; class MacOSXSocketOptions extends PlatformSocketOptions { @@ -49,6 +52,11 @@ void setTcpKeepAliveTime(int fd, final int value) throws SocketException { setTcpKeepAliveTime0(fd, value); } + @Override + boolean peerCredentialsSupported() { + return true; + } + @Override void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException { setTcpKeepAliveIntvl0(fd, value); @@ -69,12 +77,23 @@ int getTcpKeepAliveIntvl(int fd) throws SocketException { return getTcpKeepAliveIntvl0(fd); } + @Override + UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException { + long l = getSoPeerCred0(fd); + int uid = (int)(l >> 32); + int gid = (int)l; + UserPrincipal user = UnixUserPrincipals.fromUid(uid); + GroupPrincipal group = UnixUserPrincipals.fromGid(gid); + return new UnixDomainPrincipal(user, group); + } + private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; private static native int getTcpkeepAliveProbes0(int fd) throws SocketException; private static native int getTcpKeepAliveTime0(int fd) throws SocketException; private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; + private static native long getSoPeerCred0(int fd) throws SocketException; private static native boolean keepAliveOptionsSupported0(); static { if (System.getSecurityManager() == null) { diff --git a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c index c16dab1a1c7..2e908c1f918 100644 --- a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c +++ b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * questions. */ #include +#include #include #include #include @@ -123,6 +124,25 @@ JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpkeepAliveProbes0 return optval; } +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: getSoPeerCred0 + * Signature: (I)L + */ +JNIEXPORT jlong JNICALL Java_jdk_net_MacOSXSocketOptions_getSoPeerCred0 + (JNIEnv *env, jclass clazz, jint fd) { + + jint rv; + int uid, gid; + rv = getpeereid(fd, (uid_t *)&uid, (gid_t *)&gid); + handleError(env, rv, "get peer eid failed"); + if (rv == -1) { + uid = gid = -1; + } + return (((long)uid) << 32) | (gid & 0xffffffffL); +} + + /* * Class: jdk_net_MacOSXSocketOptions * Method: getTcpKeepAliveTime0 diff --git a/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java b/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java index 0a86bac9b6c..1d6855add17 100644 --- a/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java +++ b/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java @@ -180,6 +180,25 @@ private ExtendedSocketOptions() { } public static final SocketOption SO_INCOMING_NAPI_ID = new ExtSocketOption("SO_INCOMING_NAPI_ID", Integer.class); + /** + * Unix Domain peer credentials. + * + *

The value of this socket option is a {@link UnixDomainPrincipal} that + * represents the credentials of a peer connected to a Unix Domain socket. + * The credentials are those that applied at the time the socket was first + * connected or accepted. + * + *

The socket option is read-only and an attempt to set the socket option + * will throw {@code SocketException}. {@code SocketException} is also thrown + * when attempting to get the value of the socket option on an unconnected Unix + * Domain socket. + * + * @since 16 + */ + public static final SocketOption SO_PEERCRED + = new ExtSocketOption + ("SO_PEERCRED", UnixDomainPrincipal.class); + private static final PlatformSocketOptions platformSocketOptions = PlatformSocketOptions.get(); @@ -187,6 +206,8 @@ private ExtendedSocketOptions() { } platformSocketOptions.quickAckSupported(); private static final boolean keepAliveOptSupported = platformSocketOptions.keepAliveOptionsSupported(); + private static final boolean peerCredentialsSupported = + platformSocketOptions.peerCredentialsSupported(); private static final boolean incomingNapiIdOptSupported = platformSocketOptions.incomingNapiIdSupported(); private static final Set> extendedOptions = options(); @@ -202,6 +223,9 @@ static Set> options() { if (keepAliveOptSupported) { options.addAll(Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL)); } + if (peerCredentialsSupported) { + options.add(SO_PEERCRED); + } return Collections.unmodifiableSet(options); } @@ -233,6 +257,8 @@ public void setOption(FileDescriptor fd, throw new UnsupportedOperationException("Attempt to set unsupported option " + option); else throw new SocketException("Attempt to set read only option " + option); + } else if (option == SO_PEERCRED) { + throw new SocketException("SO_PEERCRED cannot be set "); } else { throw new InternalError("Unexpected option " + option); } @@ -255,6 +281,8 @@ public Object getOption(FileDescriptor fd, return getTcpKeepAliveTime(fd); } else if (option == TCP_KEEPINTERVAL) { return getTcpKeepAliveIntvl(fd); + } else if (option == SO_PEERCRED) { + return getSoPeerCred(fd); } else if (option == SO_INCOMING_NAPI_ID) { return getIncomingNapiId(fd); } else { @@ -272,6 +300,11 @@ private static void setQuickAckOption(FileDescriptor fd, boolean enable) platformSocketOptions.setQuickAck(fdAccess.get(fd), enable); } + private static Object getSoPeerCred(FileDescriptor fd) + throws SocketException { + return platformSocketOptions.getSoPeerCred(fdAccess.get(fd)); + } + private static Object getQuickAckOption(FileDescriptor fd) throws SocketException { return platformSocketOptions.getQuickAck(fdAccess.get(fd)); @@ -345,6 +378,10 @@ static PlatformSocketOptions get() { return instance; } + boolean peerCredentialsSupported() { + return false; + } + void setQuickAck(int fd, boolean on) throws SocketException { throw new UnsupportedOperationException("unsupported TCP_QUICKACK option"); } @@ -369,6 +406,10 @@ void setTcpKeepAliveTime(int fd, final int value) throws SocketException { throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option"); } + UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported SO_PEERCRED option"); + } + void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException { throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option"); } diff --git a/src/jdk.net/share/classes/jdk/net/UnixDomainPrincipal.java b/src/jdk.net/share/classes/jdk/net/UnixDomainPrincipal.java new file mode 100644 index 00000000000..0808204d373 --- /dev/null +++ b/src/jdk.net/share/classes/jdk/net/UnixDomainPrincipal.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.net; + +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.GroupPrincipal; +import java.util.Objects; + +/** + * Represents the credentials of a peer connected to a + * + * Unix domain socket. + * + * @since 16 + */ + +public final class UnixDomainPrincipal { + private final UserPrincipal user; + private final GroupPrincipal group; + + /** + * Creates a UnixDomainPrincipal. + * + * @param user the user identity + * + * @param group the group identity + * + * @throws NullPointerException if {@code user} or {@code group} are {@code null}. + */ + public UnixDomainPrincipal(UserPrincipal user, GroupPrincipal group) { + this.user = Objects.requireNonNull(user); + this.group = Objects.requireNonNull(group); + } + + /** + * Returns true if {@code obj} is a {@code UnixDomainPrincipal} + * and its user and group are equal to this user and group. + * + * @param obj the object to compare with + * @return true if this equal to obj + */ + public boolean equals(Object obj) { + if (obj instanceof UnixDomainPrincipal) { + UnixDomainPrincipal that = (UnixDomainPrincipal) obj; + return Objects.equals(this.user, that.user) + && Objects.equals(this.group, that.group); + } + return false; + } + + /** + * Returns a hashcode calculated from the user and group + */ + public int hashCode() { + return Objects.hash(user, group); + } + + /** + * Returns this object's {@link UserPrincipal} + * + * @return this object's user + */ + public UserPrincipal user() { + return user; + } + + /** + * Returns this object's {@link GroupPrincipal} + * + * @return this object's user + */ + public GroupPrincipal group() { + return group; + } +} diff --git a/test/hotspot/gtest/gc/z/test_zForwarding.cpp b/test/hotspot/gtest/gc/z/test_zForwarding.cpp index 7e7be1379b5..1da6764801f 100644 --- a/test/hotspot/gtest/gc/z/test_zForwarding.cpp +++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/z/zAddress.inline.hpp" #include "gc/z/zForwarding.inline.hpp" +#include "gc/z/zForwardingAllocator.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zPage.inline.hpp" #include "unittest.hpp" @@ -157,14 +158,16 @@ class ZForwardingTest : public Test { const size_t live_bytes = live_objects * object_size; page.inc_live(live_objects, live_bytes); + // Setup allocator + ZForwardingAllocator allocator; + const uint32_t nentries = ZForwarding::nentries(&page); + allocator.reset((sizeof(ZForwarding)) + (nentries * sizeof(ZForwardingEntry))); + // Setup forwarding - ZForwarding* const forwarding = ZForwarding::create(&page); + ZForwarding* const forwarding = ZForwarding::alloc(&allocator, &page); // Actual test function (*function)(forwarding); - - // Teardown forwarding - ZForwarding::destroy(forwarding); } // Run the given function with a few different input values. diff --git a/test/hotspot/gtest/runtime/test_stackoverflow.cpp b/test/hotspot/gtest/runtime/test_stackoverflow.cpp new file mode 100644 index 00000000000..52a7611e839 --- /dev/null +++ b/test/hotspot/gtest/runtime/test_stackoverflow.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/os.hpp" +#include "runtime/globals.hpp" +#include "runtime/stackOverflow.hpp" +#include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" +#include "unittest.hpp" + + +TEST_VM(StackOverflow, basics) { + StackOverflow so; + + // Make up a stack range. No need to allocate anything. Size has to be large enough + // to fit sum of all zones into them. + address base = (address) 0x40000000; + const size_t size = os::vm_page_size() * 100; + address end = base - size; + so.initialize(base, end); + + // Walking down the "stack" check for consistency of the three "in_stack_xxx" functions + enum { normal_stack, reserved_or_yellow_zone, red_zone } where = normal_stack; + for (address p = base - 1; p >= end; p -= os::vm_page_size()) { + // tty->print_cr(PTR_FORMAT " %d %d %d", p2i(p), + // (int)so.in_stack_reserved_zone(p), + // (int)so.in_stack_yellow_reserved_zone(p), + // (int)so.in_stack_red_zone(p)); + switch (where) { + case normal_stack: + ASSERT_FALSE(so.in_stack_red_zone(p)); + if (so.in_stack_yellow_reserved_zone(p)) { + if (StackReservedPages > 0) { + ASSERT_TRUE(so.in_stack_reserved_zone(p)); + } else { + ASSERT_FALSE(so.in_stack_reserved_zone(p)); + } + where = reserved_or_yellow_zone; + } else { + ASSERT_FALSE(so.in_stack_reserved_zone((p))); + } + break; + case reserved_or_yellow_zone: + if (so.in_stack_red_zone(p)) { + ASSERT_FALSE(so.in_stack_yellow_reserved_zone(p)); + where = red_zone; + } else { + ASSERT_TRUE(so.in_stack_yellow_reserved_zone(p)); + } + break; + case red_zone: + ASSERT_TRUE(so.in_stack_red_zone(p)); + ASSERT_FALSE(so.in_stack_yellow_reserved_zone(p)); + ASSERT_FALSE(so.in_stack_reserved_zone((p))); + break; + } + } + ASSERT_EQ(where, red_zone); + + // Check bases. + ASSERT_FALSE(so.in_stack_red_zone(so.stack_red_zone_base())); + ASSERT_TRUE(so.in_stack_red_zone(so.stack_red_zone_base() - 1)); + ASSERT_TRUE(so.in_stack_yellow_reserved_zone(so.stack_red_zone_base())); + ASSERT_FALSE(so.in_stack_reserved_zone(so.stack_reserved_zone_base())); + if (so.stack_reserved_zone_size() > 0) { + ASSERT_TRUE(so.in_stack_reserved_zone(so.stack_reserved_zone_base() - 1)); + } +} diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index a5afc8bc4e5..680184d8403 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -64,6 +64,8 @@ compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java 8183263 generic-x64 compiler/c2/Test8004741.java 8235801 generic-all +compiler/loopstripmining/BackedgeNodeWithOutOfLoopControl.java 8255120 generic-all + ############################################################################# # :hotspot_gc diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 77e1850538a..0ef3c2d2dc4 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -75,7 +75,8 @@ requires.properties= \ vm.compiler2.enabled \ vm.musl \ docker.support \ - test.vm.gc.nvdimm + test.vm.gc.nvdimm \ + jdk.containerized # Minimum jtreg version requiredVersion=5.1 b1 diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 6037df5c2b8..e5492b207c0 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -202,7 +202,6 @@ tier1_gc_2 = \ -gc/g1/ \ -gc/logging/TestUnifiedLoggingSwitchStress.java \ -gc/stress \ - -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \ -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \ -gc/shenandoah \ -gc/nvdimm @@ -307,6 +306,7 @@ tier1_runtime = \ -runtime/cds/CdsSameObjectAlignment.java \ -runtime/cds/SharedBaseAddress.java \ -runtime/Thread/CancellableThreadTest.java \ + -runtime/Thread/ThreadCountLimit.java \ -runtime/Thread/TestThreadDumpMonitorContention.java \ -runtime/Unsafe/RangeCheck.java \ sanity/ \ diff --git a/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java index 2d2e732c938..5616d5b2f6f 100644 --- a/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java +++ b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,67 +23,72 @@ /* * @test - * @bug 8204479 8253191 + * @bug 8204479 + * @summary Bitwise AND on byte value sometimes produces wrong result * - * @library /test/lib - * @modules java.base/jdk.internal.vm.annotation - * - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation compiler.c2.TestUnsignedByteCompare + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation + * -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xcomp -XX:-Inline + * compiler.c2.TestUnsignedByteCompare */ -package compiler.c2; -import java.lang.invoke.*; -import jdk.internal.vm.annotation.DontInline; -import jdk.test.lib.Asserts; +package compiler.c2; public class TestUnsignedByteCompare { - @DontInline static boolean testByteGT0(byte[] val) { return (val[0] & mask()) > 0; } - @DontInline static boolean testByteGE0(byte[] val) { return (val[0] & mask()) >= 0; } - @DontInline static boolean testByteEQ0(byte[] val) { return (val[0] & mask()) == 0; } - @DontInline static boolean testByteNE0(byte[] val) { return (val[0] & mask()) != 0; } - @DontInline static boolean testByteLE0(byte[] val) { return (val[0] & mask()) <= 0; } - @DontInline static boolean testByteLT0(byte[] val) { return (val[0] & mask()) < 0; } + static int p, n; - static void testValue(byte b) { - byte[] bs = new byte[] { b }; - Asserts.assertEquals(((b & mask()) > 0), testByteGT0(bs), errorMessage(b, "GT0")); - Asserts.assertEquals(((b & mask()) >= 0), testByteGE0(bs), errorMessage(b, "GE0")); - Asserts.assertEquals(((b & mask()) == 0), testByteEQ0(bs), errorMessage(b, "EQ0")); - Asserts.assertEquals(((b & mask()) != 0), testByteNE0(bs), errorMessage(b, "NE0")); - Asserts.assertEquals(((b & mask()) <= 0), testByteLE0(bs), errorMessage(b, "LE0")); - Asserts.assertEquals(((b & mask()) < 0), testByteLT0(bs), errorMessage(b, "LT0")); + static void report(byte[] ba, int i, boolean failed) { + // Enable for debugging: + // System.out.println((failed ? "Failed" : "Passed") + " with: " + ba[i] + " at " + i); } - public static void main(String[] args) { - for (int mask = 0; mask <= 0xFF; mask++) { - setMask(mask); - for (int i = 0; i < 20_000; i++) { - testValue((byte) i); + static void m1(byte[] ba) { + for (int i = 0; i < ba.length; i++) { + if ((ba[i] & 0xFF) < 0x10) { + p++; + report(ba, i, true); + } else { + n++; + report(ba, i, false); } } - System.out.println("TEST PASSED"); } - static String errorMessage(byte b, String type) { - return String.format("%s: val=0x%x mask=0x%x", type, b, mask()); + static void m2(byte[] ba) { + for (int i = 0; i < ba.length; i++) { + if (((ba[i] & 0xFF) & 0x80) < 0) { + p++; + report(ba, i, true); + } else { + n++; + report(ba, i, false); + } + } } - // Mutable mask as a compile-time constant. + static public void main(String[] args) { + final int tries = 1_000; + final int count = 1_000; - private static final CallSite MASK_CS = new MutableCallSite(MethodType.methodType(int.class)); - private static final MethodHandle MASK_MH = MASK_CS.dynamicInvoker(); + byte[] ba = new byte[count]; - static int mask() { - try { - return (int) MASK_MH.invokeExact(); - } catch (Throwable t) { - throw new InternalError(t); // should NOT happen + for (int i = 0; i < count; i++) { + int v = -(i % 126 + 1); + ba[i] = (byte)v; } - } - static void setMask(int mask) { - MethodHandle constant = MethodHandles.constant(int.class, mask); - MASK_CS.setTarget(constant); + for (int t = 0; t < tries; t++) { + m1(ba); + if (p != 0) { + throw new IllegalStateException("m1 error: p = " + p + ", n = " + n); + } + } + + for (int t = 0; t < tries; t++) { + m2(ba); + if (p != 0) { + throw new IllegalStateException("m2 error: p = " + p + ", n = " + n); + } + } } } diff --git a/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare1.java b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare1.java new file mode 100644 index 00000000000..ef035e89241 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare1.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8253191 + * + * @library /test/lib + * @modules java.base/jdk.internal.vm.annotation + * + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation compiler.c2.TestUnsignedByteCompare1 + */ +package compiler.c2; + +import java.lang.invoke.*; +import jdk.internal.vm.annotation.DontInline; +import jdk.test.lib.Asserts; + +public class TestUnsignedByteCompare1 { + + @DontInline static boolean testByteGT0(byte[] val) { return (val[0] & mask()) > 0; } + @DontInline static boolean testByteGE0(byte[] val) { return (val[0] & mask()) >= 0; } + @DontInline static boolean testByteEQ0(byte[] val) { return (val[0] & mask()) == 0; } + @DontInline static boolean testByteNE0(byte[] val) { return (val[0] & mask()) != 0; } + @DontInline static boolean testByteLE0(byte[] val) { return (val[0] & mask()) <= 0; } + @DontInline static boolean testByteLT0(byte[] val) { return (val[0] & mask()) < 0; } + + static void testValue(byte b) { + byte[] bs = new byte[] { b }; + Asserts.assertEquals(((b & mask()) > 0), testByteGT0(bs), errorMessage(b, "GT0")); + Asserts.assertEquals(((b & mask()) >= 0), testByteGE0(bs), errorMessage(b, "GE0")); + Asserts.assertEquals(((b & mask()) == 0), testByteEQ0(bs), errorMessage(b, "EQ0")); + Asserts.assertEquals(((b & mask()) != 0), testByteNE0(bs), errorMessage(b, "NE0")); + Asserts.assertEquals(((b & mask()) <= 0), testByteLE0(bs), errorMessage(b, "LE0")); + Asserts.assertEquals(((b & mask()) < 0), testByteLT0(bs), errorMessage(b, "LT0")); + } + + public static void main(String[] args) { + for (int mask = 0; mask <= 0xFF; mask++) { + setMask(mask); + for (int i = 0; i < 20_000; i++) { + testValue((byte) i); + } + } + System.out.println("TEST PASSED"); + } + + static String errorMessage(byte b, String type) { + return String.format("%s: val=0x%x mask=0x%x", type, b, mask()); + } + + // Mutable mask as a compile-time constant. + + private static final CallSite MASK_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final MethodHandle MASK_MH = MASK_CS.dynamicInvoker(); + + static int mask() { + try { + return (int) MASK_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static void setMask(int mask) { + MethodHandle constant = MethodHandles.constant(int.class, mask); + MASK_CS.setTarget(constant); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestSVEWithJNI.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestSVEWithJNI.java index dc15ca800df..7b7eeb75207 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestSVEWithJNI.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestSVEWithJNI.java @@ -26,7 +26,7 @@ /** * @test * - * @requires os.arch == "aarch64" & vm.compiler2.enabled + * @requires os.arch == "aarch64" & vm.compiler2.enabled & os.family == "linux" * @summary Verify VM SVE checking behavior * @library /test/lib * @run main/othervm/native compiler.c2.aarch64.TestSVEWithJNI diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVectorShiftShorts.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVectorShiftShorts.java new file mode 100644 index 00000000000..75e48ff44bb --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVectorShiftShorts.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020, 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. + */ + + +/** + * @test + * @bug 8255287 + * @summary aarch64: fix SVE patterns for vector shift count + * + * @requires os.arch == "aarch64" & vm.compiler2.enabled + * @run main/othervm -XX:UseSVE=2 -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.c2.aarch64.TestVectorShiftShorts::test_* + * compiler.c2.aarch64.TestVectorShiftShorts + */ + +package compiler.c2.aarch64; + +public class TestVectorShiftShorts { + + private static final int ARRLEN = 1000; + private static final int ITERS = 20000; + + public static void main(String args[]) { + short[] a0 = new short[ARRLEN]; + short[] a1 = new short[ARRLEN]; + + // Initialize + test_init(a0, a1); + + // Warmup + for (int i = 0; i < ITERS; i++) { + test_lshift(a0, a1); + test_urshift(a0, a1); + } + + // Test and verify results + test_init(a0, a1); + test_lshift(a0, a1); + verify_lshift(a0, a1); + + test_init(a0, a1); + test_urshift(a0, a1); + verify_urshift(a0, a1); + + // Finish + System.out.println("Test passed"); + } + + static void test_init(short[] a0, short[] a1) { + for (int i = 0; i < ARRLEN; i++) { + a0[i] = (short)(i & 3); + a1[i] = (short)i; + } + } + + static void test_lshift(short[] a0, short[] a1) { + for (int i = 0; i < ARRLEN; i++) { + a0[i] = (short)(a1[i] << 10); + } + } + + static void verify_lshift(short[] a0, short[] a1) { + for (int i = 0; i < ARRLEN; i++) { + if (a0[i] != (short)(a1[i] << 10)) { + throw new RuntimeException("LShift test failed."); + } + } + } + + static void test_urshift(short[] a0, short[] a1) { + for (int i = 0; i < ARRLEN; i++) { + a0[i] = (short)(a1[i] >>> 10); + } + } + + static void verify_urshift(short[] a0, short[] a1) { + for (int i = 0; i < ARRLEN; i++) { + if (a0[i] != (short)(a1[i] >>> 10)) { + throw new RuntimeException("URshift test failed."); + } + } + } + +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/libTestSVEWithJNI.c b/test/hotspot/jtreg/compiler/c2/aarch64/libTestSVEWithJNI.c index 0cb3ab0b5c4..2e4e883fa48 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/libTestSVEWithJNI.c +++ b/test/hotspot/jtreg/compiler/c2/aarch64/libTestSVEWithJNI.c @@ -23,7 +23,7 @@ * */ -#ifdef __aarch64__ +#if defined(__aarch64__) && defined (__linux__) #include #include diff --git a/test/hotspot/jtreg/compiler/vectorization/TestForEachRem.java b/test/hotspot/jtreg/compiler/vectorization/TestForEachRem.java new file mode 100644 index 00000000000..12c5e5ba9ad --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestForEachRem.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8251994 + * @summary Test vectorization of Streams$RangeIntSpliterator::forEachRemaining + * @requires vm.compiler2.enabled & vm.compMode != "Xint" + * + * @run main compiler.vectorization.TestForEachRem test1 + * @run main compiler.vectorization.TestForEachRem test2 + * @run main compiler.vectorization.TestForEachRem test3 + * @run main compiler.vectorization.TestForEachRem test4 + */ + +package compiler.vectorization; + +import java.util.stream.IntStream; + +public class TestForEachRem { + static final int RANGE = 512; + static final int ITER = 100; + + static void test1(int[] data) { + IntStream.range(0, RANGE).parallel().forEach(j -> { + data[j] = j + 1; + }); + } + + static void test2(int[] data) { + IntStream.range(0, RANGE - 1).forEach(j -> { + data[j] = data[j] + data[j + 1]; + }); + } + + static void test3(int[] data, int A, int B) { + IntStream.range(0, RANGE - 1).forEach(j -> { + data[j] = A * data[j] + B * data[j + 1]; + }); + } + + static void test4(int[] data) { + IntStream.range(0, RANGE - 1).forEach(j -> { + data[j + 1] = data[j]; + }); + } + + static void verify(String name, int[] data, int[] gold) { + for (int i = 0; i < RANGE; i++) { + if (data[i] != gold[i]) { + throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]); + } + } + } + + public static void main(String[] args) { + int[] data = new int[RANGE]; + int[] gold = new int[RANGE]; + + if (args.length == 0) { + throw new RuntimeException(" Missing test name: test1, test2, test3, test4"); + } + + if (args[0].equals("test1")) { + System.out.println(" Run test1 ..."); + test1(gold); + for (int i = 0; i < ITER; i++) { + test1(data); + } + verify("test1", data, gold); + System.out.println(" Finished test1."); + } + + if (args[0].equals("test2")) { + System.out.println(" Run test2 ..."); + test1(gold); + test2(gold); + for (int i = 0; i < ITER; i++) { + test1(data); // reset + test2(data); + } + verify("test2", data, gold); + System.out.println(" Finished test2."); + } + + if (args[0].equals("test3")) { + System.out.println(" Run test3 ..."); + test1(gold); + test3(gold, 2, 3); + for (int i = 0; i < ITER; i++) { + test1(data); // reset + test3(data, 2, 3); + } + verify("test3", data, gold); + System.out.println(" Finished test3."); + } + + if (args[0].equals("test4")) { + System.out.println(" Run test4 ..."); + test1(gold); // reset + test4(gold); + for (int i = 0; i < ITER; i++) { + test1(data); // reset + test4(data); + } + verify("test4", data, gold); + System.out.println(" Finished test4."); + } + } +} diff --git a/test/hotspot/jtreg/compiler/vectorization/TestOptionVectorize.java b/test/hotspot/jtreg/compiler/vectorization/TestOptionVectorize.java new file mode 100644 index 00000000000..566868f68d4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestOptionVectorize.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8251994 + * @summary Test forced vectorization + * @requires vm.compiler2.enabled & vm.compMode != "Xint" + * + * @run main/othervm -XX:CompileCommand=option,*::test,Vectorize compiler.vectorization.TestOptionVectorize + */ + +package compiler.vectorization; + +import java.util.stream.IntStream; + +public class TestOptionVectorize { + static final int RANGE = 512; + static final int ITER = 100; + + static void init(double[] data) { + IntStream.range(0, RANGE).parallel().forEach(j -> { + data[j] = j + 1; + }); + } + + static void test(double[] data, double A, double B) { + for (int i = RANGE - 1; i > 0; i--) { + for (int j = 0; j <= i - 1; j++) { + data[j] = A * data[j + 1] + B * data[j]; + } + } + } + + static void verify(double[] data, double[] gold) { + for (int i = 0; i < RANGE; i++) { + if (data[i] != gold[i]) { + throw new RuntimeException(" Invalid result: data[" + i + "]: " + data[i] + " != " + gold[i]); + } + } + } + + public static void main(String[] args) { + double[] data = new double[RANGE]; + double[] gold = new double[RANGE]; + System.out.println(" Run test ..."); + init(gold); // reset + test(gold, 1.0, 2.0); + for (int i = 0; i < ITER; i++) { + init(data); // reset + test(data, 1.0, 2.0); + } + verify(data, gold); + System.out.println(" Finished test."); + } +} diff --git a/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java b/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java index d9b3c8b7fbe..ae38b865bf8 100644 --- a/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java +++ b/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java @@ -53,6 +53,9 @@ public class CgroupSubsystemFactory { private static final int INVALID_CGROUPS_V1 = 4; private static final int INVALID_CGROUPS_NO_MOUNT = 5; private Path existingDirectory; + private Path cgroupv1CgroupsJoinControllers; + private Path cgroupv1SelfCgroupsJoinControllers; + private Path cgroupv1MountInfoJoinControllers; private Path cgroupv1CgInfoZeroHierarchy; private Path cgroupv1MntInfoZeroHierarchy; private Path cgroupv2CgInfoZeroHierarchy; @@ -81,6 +84,17 @@ public class CgroupSubsystemFactory { "1:name=systemd:/user.slice/user-15263.slice/user@15263.service/gnome-terminal-server.service\n" + "0::/user.slice/user-15263.slice/user@15263.service/gnome-terminal-server.service"; private String procSelfCgroupV2UnifiedContent = "0::/user.slice/user-1000.slice/session-3.scope"; + private String procSelfCgroupV1JoinControllers = + "9:freezer:/\n" + + "8:rdma:/\n" + + "7:blkio:/user.slice\n" + + "6:devices:/user.slice\n" + + "5:pids:/user.slice/user-1000.slice/session-2.scope\n" + + "4:cpu,cpuacct,memory,net_cls,net_prio,hugetlb:/user.slice/user-1000.slice/session-2.scope\n" + + "3:cpuset:/\n" + + "2:perf_event:/\n" + + "1:name=systemd:/user.slice/user-1000.slice/session-2.scope\n" + + "0::/user.slice/user-1000.slice/session-2.scope\n"; private String cgroupsZeroHierarchy = "#subsys_name hierarchy num_cgroups enabled\n" + "cpuset 0 1 1\n" + @@ -92,6 +106,21 @@ public class CgroupSubsystemFactory { "net_cls 0 1 1\n" + "blkio 0 1 1\n" + "perf_event 0 1 1 "; + private String cgroupsNonZeroJoinControllers = + "#subsys_name hierarchy num_cgroups enabled\n" + + "cpuset\t3\t1\t1\n" + + "cpu\t4\t153\t1\n" + + "cpuacct\t4\t153\t1\n" + + "blkio\t7\t87\t1\n" + + "memory\t4\t153\t1\n" + + "devices\t6\t87\t1\n" + + "freezer\t9\t1\t1\n" + + "net_cls\t4\t153\t1\n" + + "perf_event\t2\t1\t1\n" + + "net_prio\t4\t153\t1\n" + + "hugetlb\t4\t153\t1\n" + + "pids\t5\t95\t1\n" + + "rdma\t8\t1\t1\n"; private String cgroupV2LineHybrid = "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n"; private String cgroupv1MountInfoLineMemory = "35 30 0:31 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:7 - cgroup none rw,seclabel,memory\n"; private String mntInfoHybridStub = @@ -110,6 +139,18 @@ public class CgroupSubsystemFactory { private String mntInfoHybridMissingMemory = mntInfoHybridStub; private String mntInfoHybrid = cgroupV2LineHybrid + mntInfoHybridRest; private String mntInfoHybridFlippedOrder = mntInfoHybridRest + cgroupV2LineHybrid; + private String mntInfoCgroupv1JoinControllers = + "31 22 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755\n" + + "32 31 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate\n" + + "33 31 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd\n" + + "36 31 0:31 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,perf_event\n" + + "37 31 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,cpuset\n" + + "38 31 0:33 / /sys/fs/cgroup/cpu,cpuacct,net_cls,net_prio,hugetlb,memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,cpu,cpuacct,memory,net_cls,net_prio,hugetlb\n" + + "39 31 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,pids\n" + + "40 31 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,devices\n" + + "41 31 0:36 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,blkio\n" + + "42 31 0:37 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,rdma\n" + + "43 31 0:38 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,freezer\n"; private String mntInfoCgroupv1MoreCpusetLine = "121 32 0:37 / /cpusets rw,relatime shared:69 - cgroup none rw,cpuset\n"; private String mntInfoCgroupv1DoubleCpuset = mntInfoCgroupv1MoreCpusetLine + mntInfoHybrid; private String mntInfoCgroupv1DoubleCpuset2 = mntInfoHybrid + mntInfoCgroupv1MoreCpusetLine; @@ -175,6 +216,15 @@ private void setup() { cgroupv1MntInfoSystemdOnly = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_systemd_only"); Files.writeString(cgroupv1MntInfoSystemdOnly, mntInfoCgroupsV1SystemdOnly); + + cgroupv1CgroupsJoinControllers = Paths.get(existingDirectory.toString(), "cgroups_cgv1_join_controllers"); + Files.writeString(cgroupv1CgroupsJoinControllers, cgroupsNonZeroJoinControllers); + + cgroupv1SelfCgroupsJoinControllers = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1_join_controllers"); + Files.writeString(cgroupv1SelfCgroupsJoinControllers, procSelfCgroupV1JoinControllers); + + cgroupv1MountInfoJoinControllers = Paths.get(existingDirectory.toString(), "mntinfo_cgv1_join_controllers"); + Files.writeString(cgroupv1MountInfoJoinControllers, mntInfoCgroupv1JoinControllers); } catch (IOException e) { throw new RuntimeException(e); } @@ -192,6 +242,16 @@ private boolean isValidCgroup(int value) { return value == CGROUPS_V1 || value == CGROUPS_V2; } + public void testCgroupv1JoinControllerCombo(WhiteBox wb) { + String procCgroups = cgroupv1CgroupsJoinControllers.toString(); + String procSelfCgroup = cgroupv1SelfCgroupsJoinControllers.toString(); + String procSelfMountinfo = cgroupv1MountInfoJoinControllers.toString(); + int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo); + Asserts.assertEQ(CGROUPS_V1, retval, "Join controllers should be properly detected"); + Asserts.assertTrue(isValidCgroup(retval)); + System.out.println("testCgroupv1JoinControllerMounts PASSED!"); + } + public void testCgroupv1MultipleCpusetMounts(WhiteBox wb, Path mountInfo) { String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); String procSelfCgroup = cgroupV1SelfCgroup.toString(); @@ -287,6 +347,7 @@ public static void main(String[] args) throws Exception { test.testCgroupv2NoCgroup2Fs(wb); test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset); test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset2); + test.testCgroupv1JoinControllerCombo(wb); } finally { test.teardown(); } diff --git a/test/hotspot/jtreg/gc/arguments/TestSurvivorAlignmentInBytesOption.java b/test/hotspot/jtreg/gc/arguments/TestSurvivorAlignmentInBytesOption.java deleted file mode 100644 index 6a515c7b10c..00000000000 --- a/test/hotspot/jtreg/gc/arguments/TestSurvivorAlignmentInBytesOption.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.arguments; - -import jdk.test.lib.Platform; -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -/** - * @test - * @bug 8031323 - * @summary Verify SurvivorAlignmentInBytes option processing. - * @library /test/lib - * @requires vm.opt.SurvivorAlignmentInBytes == null - * & vm.opt.ObjectAlignmentInBytes == null - * & vm.opt.UnlockExperimentalVMOptions == null - * & (vm.opt.IgnoreUnrecognizedVMOptions == null - * | vm.opt.IgnoreUnrecognizedVMOptions == "false") - * @modules java.base/jdk.internal.misc - * java.management - * @run driver gc.arguments.TestSurvivorAlignmentInBytesOption - */ -public class TestSurvivorAlignmentInBytesOption { - public static void main(String args[]) throws Throwable { - String optionName = "SurvivorAlignmentInBytes"; - String unlockExperimentalVMOpts = "UnlockExperimentalVMOptions"; - String optionIsExperimental - = CommandLineOptionTest.getExperimentalOptionErrorMessage( - optionName); - String valueIsTooSmall= ".*SurvivorAlignmentInBytes.*must be greater" - + " than or equal to ObjectAlignmentInBytes.*"; - String mustBePowerOf2 = ".*SurvivorAlignmentInBytes.*must be " - + "power of 2.*"; - - // Verify that without -XX:+UnlockExperimentalVMOptions usage of - // SurvivorAlignmentInBytes option will cause JVM startup failure - // with the warning message saying that that option is experimental. - String shouldFailMessage = String.format("JVM option '%s' is " - + "experimental.%nJVM startup should fail without " - + "-XX:+UnlockExperimentalVMOptions option", optionName); - CommandLineOptionTest.verifyJVMStartup( - new String[]{optionIsExperimental}, null, - shouldFailMessage, shouldFailMessage, - ExitCode.FAIL, false, - "-XX:-UnlockExperimentalVMOptions", - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, false), - CommandLineOptionTest.prepareNumericFlag(optionName, 64)); - - // Verify that with -XX:+UnlockExperimentalVMOptions passed to JVM - // usage of SurvivorAlignmentInBytes option won't cause JVM startup - // failure. - String shouldPassMessage = String.format("JVM option '%s' is " - + "experimental.%nJVM startup should pass with " - + "-XX:+UnlockExperimentalVMOptions option", optionName); - String noWarningMessage = "There should be no warnings when use " - + "with -XX:+UnlockExperimentalVMOptions option"; - CommandLineOptionTest.verifyJVMStartup( - null, new String[]{optionIsExperimental}, - shouldPassMessage, noWarningMessage, - ExitCode.OK, false, - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, true), - CommandLineOptionTest.prepareNumericFlag(optionName, 64)); - - // Verify that if specified SurvivorAlignmentInBytes is lower than - // ObjectAlignmentInBytes, then the JVM startup will fail with - // appropriate error message. - if (Platform.is64bit()) { - shouldFailMessage = String.format("JVM startup should fail with " - + "'%s' option value lower than ObjectAlignmentInBytes", optionName); - CommandLineOptionTest.verifyJVMStartup( - new String[]{valueIsTooSmall}, null, - shouldFailMessage, shouldFailMessage, - ExitCode.FAIL, false, - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, true), - CommandLineOptionTest.prepareNumericFlag(optionName, 8), - CommandLineOptionTest.prepareNumericFlag("ObjectAlignmentInBytes", 16)); - } - - // Verify that if specified SurvivorAlignmentInBytes value is not - // a power of 2 then the JVM startup will fail with appropriate error - // message. - shouldFailMessage = String.format("JVM startup should fail with " - + "'%s' option value is not a power of 2", optionName); - CommandLineOptionTest.verifyJVMStartup( - new String[]{mustBePowerOf2}, null, - shouldFailMessage, shouldFailMessage, - ExitCode.FAIL, false, - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, true), - CommandLineOptionTest.prepareNumericFlag(optionName, 127)); - - // Verify that if SurvivorAlignmentInBytes has correct value, then - // the JVM will be started without errors. - shouldPassMessage = String.format("JVM startup should pass with " - + "correct '%s' option value", optionName); - noWarningMessage = String.format("There should be no warnings when use " - + "correct '%s' option value", optionName); - CommandLineOptionTest.verifyJVMStartup( - null, new String[]{".*SurvivorAlignmentInBytes.*"}, - shouldPassMessage, noWarningMessage, - ExitCode.OK, false, - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, true), - CommandLineOptionTest.prepareNumericFlag(optionName, 128)); - - // Verify that we can setup different SurvivorAlignmentInBytes values. - for (int alignment = 32; alignment <= 128; alignment *= 2) { - shouldPassMessage = String.format("JVM startup should pass with " - + "'%s' = %d", optionName, alignment); - CommandLineOptionTest.verifyOptionValue(optionName, - Integer.toString(alignment), shouldPassMessage, - CommandLineOptionTest.prepareBooleanFlag( - unlockExperimentalVMOpts, true), - CommandLineOptionTest.prepareNumericFlag( - optionName, alignment)); - } - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/AlignmentHelper.java b/test/hotspot/jtreg/gc/survivorAlignment/AlignmentHelper.java deleted file mode 100644 index 39246cadb75..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/AlignmentHelper.java +++ /dev/null @@ -1,176 +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. - */ - -package gc.survivorAlignment; - -import java.lang.management.MemoryPoolMXBean; -import java.util.Optional; - -import sun.hotspot.WhiteBox; - -/** - * Helper class aimed to provide information about alignment of objects in - * particular heap space, expected memory usage after objects' allocation so on. - */ -public class AlignmentHelper { - private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - - private static final long OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM = 8L; - - /** - * Max relative allowed actual memory usage deviation from expected memory - * usage. - */ - private static final float MAX_RELATIVE_DEVIATION = 0.05f; // 5% - - public static final long OBJECT_ALIGNMENT_IN_BYTES = Optional.ofNullable( - AlignmentHelper.WHITE_BOX.getIntxVMFlag("ObjectAlignmentInBytes")) - .orElse(AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM); - - public static final long SURVIVOR_ALIGNMENT_IN_BYTES = Optional.ofNullable( - AlignmentHelper.WHITE_BOX.getIntxVMFlag("SurvivorAlignmentInBytes")) - .orElseThrow(() ->new AssertionError( - "Unable to get SurvivorAlignmentInBytes value")); - /** - * Min amount of memory that will be occupied by an object. - */ - public static final long MIN_OBJECT_SIZE - = AlignmentHelper.WHITE_BOX.getObjectSize(new Object()); - /** - * Min amount of memory that will be occupied by an empty byte array. - */ - public static final long MIN_ARRAY_SIZE - = AlignmentHelper.WHITE_BOX.getObjectSize(new byte[0]); - - /** - * Precision at which actual memory usage in a heap space represented by - * this sizing helper could be measured. - */ - private final long memoryUsageMeasurementPrecision; - /** - * Min amount of memory that will be occupied by an object allocated in a - * heap space represented by this sizing helper. - */ - private final long minObjectSizeInThisSpace; - /** - * Object's alignment in a heap space represented by this sizing helper. - */ - private final long objectAlignmentInThisRegion; - /** - * MemoryPoolMXBean associated with a heap space represented by this sizing - * helper. - */ - private final MemoryPoolMXBean poolMXBean; - - private static long alignUp(long value, long alignment) { - return ((value - 1) / alignment + 1) * alignment; - } - - protected AlignmentHelper(long memoryUsageMeasurementPrecision, - long objectAlignmentInThisRegion, long minObjectSizeInThisSpace, - MemoryPoolMXBean poolMXBean) { - this.memoryUsageMeasurementPrecision = memoryUsageMeasurementPrecision; - this.minObjectSizeInThisSpace = minObjectSizeInThisSpace; - this.objectAlignmentInThisRegion = objectAlignmentInThisRegion; - this.poolMXBean = poolMXBean; - } - - /** - * Returns how many objects have to be allocated to fill - * {@code memoryToFill} bytes in this heap space using objects of size - * {@code objectSize}. - */ - public int getObjectsCount(long memoryToFill, long objectSize) { - return (int) (memoryToFill / getObjectSizeInThisSpace(objectSize)); - } - - /** - * Returns amount of memory that {@code objectsCount} of objects with size - * {@code objectSize} will occupy this this space after allocation. - */ - public long getExpectedMemoryUsage(long objectSize, int objectsCount) { - long correctedObjectSize = getObjectSizeInThisSpace(objectSize); - return AlignmentHelper.alignUp(correctedObjectSize * objectsCount, - memoryUsageMeasurementPrecision); - } - - /** - * Returns current memory usage in this heap space. - */ - public long getActualMemoryUsage() { - return poolMXBean.getUsage().getUsed(); - } - - /** - * Returns maximum memory usage deviation from {@code expectedMemoryUsage} - * given the max allowed relative deviation equal to - * {@code relativeDeviation}. - * - * Note that value returned by this method is aligned according to - * memory measurement precision for this heap space. - */ - public long getAllowedMemoryUsageDeviation(long expectedMemoryUsage) { - long unalignedDeviation = (long) (expectedMemoryUsage * - AlignmentHelper.MAX_RELATIVE_DEVIATION); - return AlignmentHelper.alignUp(unalignedDeviation, - memoryUsageMeasurementPrecision); - } - - /** - * Returns amount of memory that will be occupied by an object with size - * {@code objectSize} in this heap space. - */ - public long getObjectSizeInThisSpace(long objectSize) { - objectSize = Math.max(objectSize, minObjectSizeInThisSpace); - - long alignedObjectSize = AlignmentHelper.alignUp(objectSize, - objectAlignmentInThisRegion); - long sizeDiff = alignedObjectSize - objectSize; - - // If there is not enough space to fit padding object, then object will - // be aligned to {@code 2 * objectAlignmentInThisRegion}. - if (sizeDiff >= AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES - && sizeDiff < AlignmentHelper.MIN_OBJECT_SIZE) { - alignedObjectSize += AlignmentHelper.MIN_OBJECT_SIZE; - alignedObjectSize = AlignmentHelper.alignUp(alignedObjectSize, - objectAlignmentInThisRegion); - } - - return alignedObjectSize; - } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - - builder.append(String.format("AlignmentHelper for memory pool '%s':%n", - poolMXBean.getName())); - builder.append(String.format("Memory usage measurement precision: %d%n", - memoryUsageMeasurementPrecision)); - builder.append(String.format("Min object size in this space: %d%n", - minObjectSizeInThisSpace)); - builder.append(String.format("Object alignment in this space: %d%n", - objectAlignmentInThisRegion)); - - return builder.toString(); - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/SurvivorAlignmentTestMain.java b/test/hotspot/jtreg/gc/survivorAlignment/SurvivorAlignmentTestMain.java deleted file mode 100644 index 6e2a70722b3..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/SurvivorAlignmentTestMain.java +++ /dev/null @@ -1,395 +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. - */ - -package gc.survivorAlignment; - -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import jdk.test.lib.Asserts; -import com.sun.management.ThreadMXBean; -import sun.hotspot.WhiteBox; -import jdk.internal.misc.Unsafe; - -/** - * Main class for tests on {@code SurvivorAlignmentInBytes} option. - * - * Typical usage is to obtain instance using fromArgs method, allocate objects - * and verify that actual memory usage in tested heap space is close to - * expected. - */ -public class SurvivorAlignmentTestMain { - enum HeapSpace { - EDEN, - SURVIVOR, - TENURED - } - - public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - - public static final long MAX_TENURING_THRESHOLD = Optional.ofNullable( - SurvivorAlignmentTestMain.WHITE_BOX.getIntxVMFlag( - "MaxTenuringThreshold")).orElse(15L); - - /** - * Regexp used to parse memory size params, like 2G, 34m or 15k. - */ - private static final Pattern SIZE_REGEX - = Pattern.compile("(?[0-9]+)(?[GMKgmk])?"); - - // Names of different heap spaces. - private static final String DEF_NEW_EDEN = "Eden Space"; - private static final String DEF_NEW_SURVIVOR = "Survivor Space"; - private static final String PAR_NEW_EDEN = "Par Eden Space"; - private static final String PAR_NEW_SURVIVOR = "Par Survivor Space"; - private static final String PS_EDEN = "PS Eden Space"; - private static final String PS_SURVIVOR = "PS Survivor Space"; - private static final String G1_EDEN = "G1 Eden Space"; - private static final String G1_SURVIVOR = "G1 Survivor Space"; - private static final String SERIAL_TENURED = "Tenured Gen"; - private static final String PS_TENURED = "PS Old Gen"; - private static final String G1_TENURED = "G1 Old Gen"; - - private static final long G1_HEAP_REGION_SIZE = Optional.ofNullable( - SurvivorAlignmentTestMain.WHITE_BOX.getUintxVMFlag( - "G1HeapRegionSize")).orElse(-1L); - - private static final AlignmentHelper EDEN_SPACE_HELPER; - private static final AlignmentHelper SURVIVOR_SPACE_HELPER; - private static final AlignmentHelper TENURED_SPACE_HELPER; - /** - * Amount of memory that should be filled during a test run. - */ - private final long memoryToFill; - /** - * The size of an objects that will be allocated during a test run. - */ - private final long objectSize; - /** - * Amount of memory that will be actually occupied by an object in eden - * space. - */ - private final long actualObjectSize; - /** - * Storage for allocated objects. - */ - private final Object[] garbage; - /** - * Heap space whose memory usage is a subject of assertions during the test - * run. - */ - private final HeapSpace testedSpace; - - private long[] baselinedThreadMemoryUsage = null; - private long[] threadIds = null; - - /** - * Initialize {@code EDEN_SPACE_HELPER}, {@code SURVIVOR_SPACE_HELPER} and - * {@code TENURED_SPACE_HELPER} to represent heap spaces in use. - * - * Note that regardless to GC object's alignment in survivor space is - * expected to be equal to {@code SurvivorAlignmentInBytes} value and - * alignment in other spaces is expected to be equal to - * {@code ObjectAlignmentInBytes} value. - * - * For G1 GC MXBeans could report memory usage only with region size - * precision (if an object allocated in some G1 heap region, then all region - * will claimed as used), so for G1's spaces precision is equal to - * {@code G1HeapRegionSize} value. - */ - static { - AlignmentHelper edenHelper = null; - AlignmentHelper survivorHelper = null; - AlignmentHelper tenuredHelper = null; - for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) { - switch (pool.getName()) { - case SurvivorAlignmentTestMain.DEF_NEW_EDEN: - case SurvivorAlignmentTestMain.PAR_NEW_EDEN: - case SurvivorAlignmentTestMain.PS_EDEN: - Asserts.assertNull(edenHelper, - "Only one bean for eden space is expected."); - edenHelper = new AlignmentHelper( - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.MIN_OBJECT_SIZE, pool); - break; - case SurvivorAlignmentTestMain.G1_EDEN: - Asserts.assertNull(edenHelper, - "Only one bean for eden space is expected."); - edenHelper = new AlignmentHelper( - SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE, - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.MIN_OBJECT_SIZE, pool); - break; - case SurvivorAlignmentTestMain.DEF_NEW_SURVIVOR: - case SurvivorAlignmentTestMain.PAR_NEW_SURVIVOR: - case SurvivorAlignmentTestMain.PS_SURVIVOR: - Asserts.assertNull(survivorHelper, - "Only one bean for survivor space is expected."); - survivorHelper = new AlignmentHelper( - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES, - AlignmentHelper.MIN_OBJECT_SIZE, pool); - break; - case SurvivorAlignmentTestMain.G1_SURVIVOR: - Asserts.assertNull(survivorHelper, - "Only one bean for survivor space is expected."); - survivorHelper = new AlignmentHelper( - SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE, - AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES, - AlignmentHelper.MIN_OBJECT_SIZE, pool); - break; - case SurvivorAlignmentTestMain.SERIAL_TENURED: - case SurvivorAlignmentTestMain.PS_TENURED: - case SurvivorAlignmentTestMain.G1_TENURED: - Asserts.assertNull(tenuredHelper, - "Only one bean for tenured space is expected."); - tenuredHelper = new AlignmentHelper( - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, - AlignmentHelper.MIN_OBJECT_SIZE, pool); - break; - } - } - EDEN_SPACE_HELPER = Objects.requireNonNull(edenHelper, - "AlignmentHelper for eden space should be initialized."); - SURVIVOR_SPACE_HELPER = Objects.requireNonNull(survivorHelper, - "AlignmentHelper for survivor space should be initialized."); - TENURED_SPACE_HELPER = Objects.requireNonNull(tenuredHelper, - "AlignmentHelper for tenured space should be initialized."); - } - /** - * Returns an SurvivorAlignmentTestMain instance constructed using CLI - * options. - * - * Following options are expected: - *

    - *
  • memoryToFill
  • - *
  • objectSize
  • - *
- * - * Both argument may contain multiplier suffix k, m or g. - */ - public static SurvivorAlignmentTestMain fromArgs(String[] args) { - Asserts.assertEQ(args.length, 3, "Expected three arguments: " - + "memory size, object size and tested heap space name."); - - long memoryToFill = parseSize(args[0]); - long objectSize = Math.max(parseSize(args[1]), - AlignmentHelper.MIN_ARRAY_SIZE); - HeapSpace testedSpace = HeapSpace.valueOf(args[2]); - - return new SurvivorAlignmentTestMain(memoryToFill, objectSize, - testedSpace); - } - - /** - * Returns a value parsed from a string with format - * <integer><multiplier>. - */ - private static long parseSize(String sizeString) { - Matcher matcher = SIZE_REGEX.matcher(sizeString); - Asserts.assertTrue(matcher.matches(), - "sizeString should have following format \"[0-9]+([MBK])?\""); - long size = Long.valueOf(matcher.group("size")); - - if (matcher.group("multiplier") != null) { - long K = 1024L; - // fall through multipliers - switch (matcher.group("multiplier").toLowerCase()) { - case "g": - size *= K; - case "m": - size *= K; - case "k": - size *= K; - } - } - return size; - } - - private SurvivorAlignmentTestMain(long memoryToFill, long objectSize, - HeapSpace testedSpace) { - this.objectSize = objectSize; - this.memoryToFill = memoryToFill; - this.testedSpace = testedSpace; - - AlignmentHelper helper = SurvivorAlignmentTestMain.EDEN_SPACE_HELPER; - - this.actualObjectSize = helper.getObjectSizeInThisSpace( - this.objectSize); - int arrayLength = helper.getObjectsCount(memoryToFill, this.objectSize); - garbage = new Object[arrayLength]; - } - - /** - * Allocate byte arrays to fill {@code memoryToFill} memory. - */ - public void allocate() { - int byteArrayLength = Math.max((int) (objectSize - - Unsafe.ARRAY_BYTE_BASE_OFFSET), 0); - - for (int i = 0; i < garbage.length; i++) { - garbage[i] = new byte[byteArrayLength]; - } - } - - /** - * Release memory occupied after {@code allocate} call. - */ - public void release() { - for (int i = 0; i < garbage.length; i++) { - garbage[i] = null; - } - } - - /** - * Returns expected amount of memory occupied in a {@code heapSpace} by - * objects referenced from {@code garbage} array. - */ - public long getExpectedMemoryUsage() { - AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace); - return alignmentHelper.getExpectedMemoryUsage(objectSize, - garbage.length); - } - - /** - * Verifies that memory usage in a {@code heapSpace} deviates from - * {@code expectedUsage} for no more than {@code MAX_RELATIVE_DEVIATION}. - */ - public void verifyMemoryUsage(long expectedUsage) { - AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace); - - long actualMemoryUsage = alignmentHelper.getActualMemoryUsage(); - boolean otherThreadsAllocatedMemory = areOtherThreadsAllocatedMemory(); - - long memoryUsageDiff = Math.abs(actualMemoryUsage - expectedUsage); - long maxAllowedUsageDiff - = alignmentHelper.getAllowedMemoryUsageDeviation(expectedUsage); - - System.out.println("Verifying memory usage in space: " + testedSpace); - System.out.println("Allocated objects count: " + garbage.length); - System.out.println("Desired object size: " + objectSize); - System.out.println("Actual object size: " + actualObjectSize); - System.out.println("Expected object size in space: " - + alignmentHelper.getObjectSizeInThisSpace(objectSize)); - System.out.println("Expected memory usage: " + expectedUsage); - System.out.println("Actual memory usage: " + actualMemoryUsage); - System.out.println("Memory usage diff: " + memoryUsageDiff); - System.out.println("Max allowed usage diff: " + maxAllowedUsageDiff); - - if (memoryUsageDiff > maxAllowedUsageDiff - && otherThreadsAllocatedMemory) { - System.out.println("Memory usage diff is incorrect, but it seems " - + "like someone else allocated objects"); - return; - } - - Asserts.assertLTE(memoryUsageDiff, maxAllowedUsageDiff, - "Actual memory usage should not deviate from expected for " + - "more then " + maxAllowedUsageDiff); - } - - /** - * Baselines amount of memory allocated by each thread. - */ - public void baselineMemoryAllocation() { - ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); - threadIds = bean.getAllThreadIds(); - baselinedThreadMemoryUsage = bean.getThreadAllocatedBytes(threadIds); - } - - /** - * Checks if threads other then the current thread were allocating objects - * after baselinedThreadMemoryUsage call. - * - * If baselinedThreadMemoryUsage was not called, then this method will return - * {@code false}. - */ - public boolean areOtherThreadsAllocatedMemory() { - if (baselinedThreadMemoryUsage == null) { - return false; - } - - ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); - long currentMemoryAllocation[] - = bean.getThreadAllocatedBytes(threadIds); - boolean otherThreadsAllocatedMemory = false; - - System.out.println("Verifying amount of memory allocated by threads:"); - for (int i = 0; i < threadIds.length; i++) { - System.out.format("Thread %d%nbaseline allocation: %d" - + "%ncurrent allocation:%d%n", threadIds[i], - baselinedThreadMemoryUsage[i], currentMemoryAllocation[i]); - System.out.println(bean.getThreadInfo(threadIds[i])); - - long bytesAllocated = Math.abs(currentMemoryAllocation[i] - - baselinedThreadMemoryUsage[i]); - if (bytesAllocated > 0 - && threadIds[i] != Thread.currentThread().getId()) { - otherThreadsAllocatedMemory = true; - } - } - - return otherThreadsAllocatedMemory; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - - builder.append(String.format("SurvivorAlignmentTestMain info:%n")); - builder.append(String.format("Desired object size: %d%n", objectSize)); - builder.append(String.format("Memory to fill: %d%n", memoryToFill)); - builder.append(String.format("Objects to be allocated: %d%n", - garbage.length)); - - builder.append(String.format("Alignment helpers to be used: %n")); - for (HeapSpace heapSpace: HeapSpace.values()) { - builder.append(String.format("For space %s:%n%s%n", heapSpace, - getAlignmentHelper(heapSpace))); - } - - return builder.toString(); - } - - /** - * Returns {@code AlignmentHelper} for a space {@code heapSpace}. - */ - public static AlignmentHelper getAlignmentHelper(HeapSpace heapSpace) { - switch (heapSpace) { - case EDEN: - return SurvivorAlignmentTestMain.EDEN_SPACE_HELPER; - case SURVIVOR: - return SurvivorAlignmentTestMain.SURVIVOR_SPACE_HELPER; - case TENURED: - return SurvivorAlignmentTestMain.TENURED_SPACE_HELPER; - default: - throw new Error("Unexpected heap space: " + heapSpace); - } - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java b/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java deleted file mode 100644 index 45db235a50c..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestAllocationInEden - * @bug 8031323 - * @summary Verify that object's alignment in eden space is not affected by - * SurvivorAlignmentInBytes option. - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 9 EDEN - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 47 EDEN - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 9 EDEN - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 87 EDEN - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 9 EDEN - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB -XX:-ResizePLAB - * -XX:OldSize=128m -XX:MaxHeapSize=192m - * -XX:-ExplicitGCInvokesConcurrent - * gc.survivorAlignment.TestAllocationInEden 10m 147 EDEN - */ -public class TestAllocationInEden { - public static void main(String args[]) { - SurvivorAlignmentTestMain test - = SurvivorAlignmentTestMain.fromArgs(args); - System.out.println(test); - - long expectedMemoryUsage = test.getExpectedMemoryUsage(); - test.baselineMemoryAllocation(); - System.gc(); - - test.allocate(); - - test.verifyMemoryUsage(expectedMemoryUsage); - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java deleted file mode 100644 index cdbc1ffc0a0..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestPromotionFromEdenToTenured - * @bug 8031323 - * @summary Verify that objects promoted from eden space to tenured space during - * full GC are not aligned to SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 9 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 47 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:MaxHeapSize=96m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 9 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:MaxHeapSize=128m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 87 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32M -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 9 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromEdenToTenured 10m 147 TENURED - */ -public class TestPromotionFromEdenToTenured { - public static void main(String args[]) { - SurvivorAlignmentTestMain test - = SurvivorAlignmentTestMain.fromArgs(args); - System.out.println(test); - - long expectedMemoryUsage = test.getExpectedMemoryUsage(); - test.baselineMemoryAllocation(); - System.gc(); - // increase expected usage by current old gen usage - expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( - SurvivorAlignmentTestMain.HeapSpace.TENURED) - .getActualMemoryUsage(); - - test.allocate(); - System.gc(); - - test.verifyMemoryUsage(expectedMemoryUsage); - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java deleted file mode 100644 index 0f926f1d596..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC - * @bug 8031323 - * @summary Verify that objects promoted from survivor space to tenured space - * during full GC are not aligned to SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:MaxHeapSize=160m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:MaxHeapSize=160m -XX:-ResizePLAB - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 20m 47 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m - * -XX:OldSize=32m -XX:MaxHeapSize=232m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:MaxHeapSize=160m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 20m 87 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m - * -XX:OldSize=32M -XX:MaxHeapSize=288m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:MaxHeapSize=160m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC 20m 147 - * TENURED - */ -public class TestPromotionFromSurvivorToTenuredAfterFullGC { - public static void main(String args[]) { - SurvivorAlignmentTestMain test - = SurvivorAlignmentTestMain.fromArgs(args); - System.out.println(test); - - long expectedMemoryUsage = test.getExpectedMemoryUsage(); - test.baselineMemoryAllocation(); - System.gc(); - // increase expected usage by current old gen usage - expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( - SurvivorAlignmentTestMain.HeapSpace.TENURED) - .getActualMemoryUsage(); - - test.allocate(); - SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); - System.gc(); - - test.verifyMemoryUsage(expectedMemoryUsage); - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java deleted file mode 100644 index 8f45164163d..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC - * @bug 8031323 - * @summary Verify that objects promoted from survivor space to tenured space - * when their age exceeded tenuring threshold are not aligned to - * SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 47 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m - * -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 87 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m - * -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 - * TENURED - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB - * -XX:-ExplicitGCInvokesConcurrent - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 - * gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 147 - * TENURED - */ -public class TestPromotionFromSurvivorToTenuredAfterMinorGC { - public static void main(String args[]) throws Exception { - SurvivorAlignmentTestMain test - = SurvivorAlignmentTestMain.fromArgs(args); - System.out.println(test); - - long expectedMemoryUsage = test.getExpectedMemoryUsage(); - test.baselineMemoryAllocation(); - SurvivorAlignmentTestMain.WHITE_BOX.fullGC(); - // increase expected usage by current old gen usage - expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( - SurvivorAlignmentTestMain.HeapSpace.TENURED) - .getActualMemoryUsage(); - - test.allocate(); - for (int i = 0; i <= SurvivorAlignmentTestMain.MAX_TENURING_THRESHOLD; i++) { - SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); - } - - // Sometimes we see that data unrelated to the test has been allocated during - // the loop. This data is included in the expectedMemoryUsage since we look - // through all threads to see what they allocated. If this data is still in - // the survivor area however, it should not be included in expectedMemoryUsage - // since the verification below only look at what's in tenured space. - expectedMemoryUsage -= SurvivorAlignmentTestMain.getAlignmentHelper( - SurvivorAlignmentTestMain.HeapSpace.SURVIVOR) - .getActualMemoryUsage(); - test.verifyMemoryUsage(expectedMemoryUsage); - } -} diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java deleted file mode 100644 index e0a92f550d4..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestPromotionLABLargeSurvivorAlignment - * @bug 8060463 - * @summary Verify that objects promoted from eden space to survivor space - * with large values for SurvivorAlignmentInBytes succeed. - * @requires vm.opt.ExplicitGCInvokesConcurrent != true - * @run main/othervm -Xmx128m - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=8 -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionLABLargeSurvivorAlignment - * @run main/othervm -Xmx128m - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=16 -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionLABLargeSurvivorAlignment - * @run main/othervm -Xmx128m - * -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=256 -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionLABLargeSurvivorAlignment - */ -public class TestPromotionLABLargeSurvivorAlignment { - public static void main(String args[]) { - Object garbage[] = new Object[1000000]; - for (int i = 0; i < garbage.length; i++) { - garbage[i] = new byte[0]; - } - for (int i = 0; i < 2; i++) { - System.gc(); - } - } -} - diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java deleted file mode 100644 index 3a6cb7e3421..00000000000 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.survivorAlignment; - -/** - * @test gc.survivorAlignment.TestPromotionToSurvivor - * @bug 8031323 - * @summary Verify that objects promoted from eden space to survivor space after - * minor GC are aligned to SurvivorAlignmentInBytes. - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m - * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 10m 9 SURVIVOR - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m - * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 20m 47 SURVIVOR - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m - * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 8m 9 SURVIVOR - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m - * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 20m 87 SURVIVOR - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m - * -XX:MaxHeapSize=384m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 10m 9 SURVIVOR - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m - * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB - * gc.survivorAlignment.TestPromotionToSurvivor 20m 147 SURVIVOR - */ -public class TestPromotionToSurvivor { - public static void main(String args[]) { - SurvivorAlignmentTestMain test - = SurvivorAlignmentTestMain.fromArgs(args); - System.out.println(test); - - long expectedUsage = test.getExpectedMemoryUsage(); - test.baselineMemoryAllocation(); - SurvivorAlignmentTestMain.WHITE_BOX.fullGC(); - - test.allocate(); - SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); - - test.verifyMemoryUsage(expectedUsage); - } -} diff --git a/test/hotspot/jtreg/gtest/MetaspaceGtests.java b/test/hotspot/jtreg/gtest/MetaspaceGtests.java index efbd18327c9..f44315ea35d 100644 --- a/test/hotspot/jtreg/gtest/MetaspaceGtests.java +++ b/test/hotspot/jtreg/gtest/MetaspaceGtests.java @@ -87,6 +87,7 @@ /* @test id=balanced-no-ccs * @summary Run metaspace-related gtests with compressed class pointers off + * @requires vm.bits == 64 * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml diff --git a/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java b/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java index 6523db8ff43..1324f1797b5 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java +++ b/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java @@ -87,8 +87,8 @@ public static void main(String[] args) throws Exception { long commitLimit = (i == 1) ? 1024 * 256 : 0; // Note: reserve limit must be a multiple of Metaspace::reserve_alignment_words() - // (512 K) - long reserveLimit = (i == 2) ? 1024 * 512 : 0; + // (512K on 64bit, 1M on 32bit) + long reserveLimit = (i == 2) ? 1024 * 1024 : 0; System.out.println("#### Test: "); System.out.println("#### testAllocationCeiling: " + testAllocationCeiling); diff --git a/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java b/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java index ce75c621e23..06ec5357ee8 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java +++ b/test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java @@ -87,8 +87,8 @@ public static void main(String[] args) throws Exception { long commitLimit = (i == 1) ? 1024 * 256 : 0; // Note: reserve limit must be a multiple of Metaspace::reserve_alignment_words() - // (512 K) - long reserveLimit = (i == 2) ? 1024 * 512 : 0; + // (512K on 64bit, 1M on 32bit) + long reserveLimit = (i == 2) ? 1024 * 1024 : 0; System.out.println("#### Test: "); System.out.println("#### testAllocationCeiling: " + testAllocationCeiling); diff --git a/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java b/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java index af61104b7e5..db8a263be5d 100644 --- a/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java +++ b/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java @@ -24,6 +24,7 @@ /** * @test * @summary Stress test that reaches the process limit for thread count, or time limit. + * @key stress * @run main ThreadCountLimit */ diff --git a/test/hotspot/jtreg/runtime/records/RedefineRecord.java b/test/hotspot/jtreg/runtime/records/RedefineRecord.java index fc37a82f72e..2617421dd57 100644 --- a/test/hotspot/jtreg/runtime/records/RedefineRecord.java +++ b/test/hotspot/jtreg/runtime/records/RedefineRecord.java @@ -23,15 +23,15 @@ /* * @test + * @bug 8246774 * @library /test/lib * @summary Test that a class that is a record can be redefined. * @modules java.base/jdk.internal.misc * @modules java.instrument * jdk.jartool/sun.tools.jar * @requires vm.jvmti - * @compile --enable-preview -source ${jdk.version} RedefineRecord.java - * @run main/othervm --enable-preview RedefineRecord buildagent - * @run main/othervm/timeout=6000 --enable-preview RedefineRecord runtest + * @run main RedefineRecord buildagent + * @run main/othervm/timeout=6000 RedefineRecord runtest */ import java.io.FileNotFoundException; @@ -100,7 +100,6 @@ public static void main(String argv[]) throws Exception { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m", "-javaagent:redefineagent.jar", - "--enable-preview", "RedefineRecord"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotContain("processing of -javaagent failed"); diff --git a/test/hotspot/jtreg/runtime/records/abstractRecord.jcod b/test/hotspot/jtreg/runtime/records/abstractRecord.jcod index 494af79f3cc..0587cfd39f0 100644 --- a/test/hotspot/jtreg/runtime/records/abstractRecord.jcod +++ b/test/hotspot/jtreg/runtime/records/abstractRecord.jcod @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,11 @@ // This test was generated from this source and then modified: // record recordNames(int x, String y) {} -// This test is a Record marked as abstract. It should result in a -// ClassFormatError exception. +// This test is a Record marked as abstract. Loading this class should +// not cause a ClassFormatError exception. class abstractRecord { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty diff --git a/test/hotspot/jtreg/runtime/records/badRecordAttribute.jcod b/test/hotspot/jtreg/runtime/records/badRecordAttribute.jcod index a0e3638da03..c95e8e6c427 100644 --- a/test/hotspot/jtreg/runtime/records/badRecordAttribute.jcod +++ b/test/hotspot/jtreg/runtime/records/badRecordAttribute.jcod @@ -28,7 +28,7 @@ // Utf8. It should result in a ClassFormatError exception. class badRecordAttribute { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty diff --git a/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java b/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java deleted file mode 100644 index 8d864dca5ab..00000000000 --- a/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary test logging of reasons for ignoring Record attribute - * @library /test/lib - * @compile superNotJLRecord.jcod recordIgnoredVersion.jcod - * @run driver ignoreRecordAttribute - */ - -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; - -public class ignoreRecordAttribute { - - public static void main(String[] args) throws Exception { - String MAJOR_VERSION = Integer.toString(44 + Runtime.version().feature()); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--enable-preview", - "-Xlog:class+record", "-Xshare:off", "superNotJLRecord"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Ignoring Record attribute"); - output.shouldContain("because super type is not java.lang.Record"); - - pb = ProcessTools.createJavaProcessBuilder("--enable-preview", - "-Xlog:class+record", "-Xshare:off", "recordIgnoredVersion"); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("Ignoring Record attribute"); - output.shouldContain("because class file version is not " + MAJOR_VERSION + ".65535"); - } - -} diff --git a/test/hotspot/jtreg/runtime/records/notFinalRecord.jcod b/test/hotspot/jtreg/runtime/records/notFinalRecord.jcod index 3ee433794d5..a5a24876f5a 100644 --- a/test/hotspot/jtreg/runtime/records/notFinalRecord.jcod +++ b/test/hotspot/jtreg/runtime/records/notFinalRecord.jcod @@ -24,11 +24,11 @@ // This test was generated from this source and then modified: // record recordNames(int x, String y) {} -// This test is a Record but not marked final. It should result in a -// ClassFormatError exception. +// This test is a Record but not marked final. Loading this class should +// not cause a ClassFormatError exception. class notFinalRecord { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty diff --git a/test/hotspot/jtreg/runtime/records/recordAttributeTest.java b/test/hotspot/jtreg/runtime/records/recordAttributeTest.java index 212ed6e3711..839334cc44a 100644 --- a/test/hotspot/jtreg/runtime/records/recordAttributeTest.java +++ b/test/hotspot/jtreg/runtime/records/recordAttributeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @compile abstractRecord.jcod notFinalRecord.jcod oldRecordAttribute.jcod superNotJLRecord.jcod * @compile shortRecordAttribute.jcod twoRecordAttributes.jcod badRecordAttribute.jcod - * - * @run main/othervm --enable-preview recordAttributeTest + * @run main recordAttributeTest */ @@ -37,7 +37,7 @@ public class recordAttributeTest { public static void runTest(String className, String cfeMessage) { try { Class newClass = Class.forName(className); - throw new RuntimeException("Expected ClasFormatError exception not thrown"); + throw new RuntimeException("Expected ClassFormatError exception not thrown"); } catch (java.lang.ClassFormatError e) { String eMsg = e.getMessage(); if (!eMsg.contains(cfeMessage)) { @@ -54,13 +54,11 @@ public static void main(String... args) throws Throwable { runTest("twoRecordAttributes", "Multiple Record attributes in class"); - // Test loading a Record type marked abstract. This should throw ClassFormatError. - runTest("abstractRecord", - "Record attribute in non-final or abstract class"); + // Test loading a Record type marked abstract. This should not throw ClassFormatError. + Class abstractClass = Class.forName("abstractRecord"); - // Test loading a Record type that is not final. This should throw ClassFormatError. - runTest("notFinalRecord", - "Record attribute in non-final or abstract class"); + // Test loading a Record type that is not final. This should not throw ClassFormatError. + Class notFinalClass = Class.forName("notFinalRecord"); // Test loading a Record type that is badly formed. This should throw ClassFormatError. runTest("badRecordAttribute", @@ -73,8 +71,13 @@ public static void main(String... args) throws Throwable { // badly formed Record attribute. No exception should be thrown. Class newClass = Class.forName("oldRecordAttribute"); - // Test that loading a class whose super class is not java.lang.Record - // ignores a badly formed Record attribute. No exception should be thrown. - newClass = Class.forName("superNotJLRecord"); + // Test that loading a class containing an ill-formed Record attribute causes a + // ClassFormatError exception even though its super class is not java.lang.Record. + runTest("superNotJLRecord", "Truncated class file"); + + // Test that loading a class that contains a properly formed Record attribute + // does not cause a ClassFormatError exception even though its super class is not + // java.lang.Record. + Class superNoJLRClass = Class.forName("superNotJLRecordOK"); } } diff --git a/test/hotspot/jtreg/runtime/records/recordIgnoredVersion.jcod b/test/hotspot/jtreg/runtime/records/recordIgnoredVersion.jcod deleted file mode 100644 index b9b5d7c312d..00000000000 --- a/test/hotspot/jtreg/runtime/records/recordIgnoredVersion.jcod +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// Record attribute is ignored because class file minor version is 0. -class recordIgnoredVersion { - 0xCAFEBABE; - 0; // minor version - 60; // version - [52] { // Constant Pool - ; // first element is empty - Method #2 #3; // #1 at 0x0A - class #4; // #2 at 0x0F - NameAndType #5 #6; // #3 at 0x12 - Utf8 "java/lang/Record"; // #4 at 0x17 - Utf8 ""; // #5 at 0x2A - Utf8 "()V"; // #6 at 0x33 - Field #8 #9; // #7 at 0x39 - class #10; // #8 at 0x3E - NameAndType #11 #12; // #9 at 0x41 - Utf8 "recordIgnoredVersion"; // #10 at 0x46 - Utf8 "x"; // #11 at 0x56 - Utf8 "I"; // #12 at 0x5A - Field #8 #9; // #13 at 0x5E - InvokeDynamic 0s #15; // #14 at 0x63 - NameAndType #16 #17; // #15 at 0x68 - Utf8 "toString"; // #16 at 0x6D - Utf8 "(LrecordIgnoredVersion;)Ljava/lang/String;"; // #17 at 0x78 - InvokeDynamic 0s #19; // #18 at 0x9E - NameAndType #20 #21; // #19 at 0xA3 - Utf8 "hashCode"; // #20 at 0xA8 - Utf8 "(LrecordIgnoredVersion;)I"; // #21 at 0xB3 - InvokeDynamic 0s #23; // #22 at 0xC8 - NameAndType #24 #25; // #23 at 0xCD - Utf8 "equals"; // #24 at 0xD2 - Utf8 "(LrecordIgnoredVersion;Ljava/lang/Object;)Z"; // #25 at 0xDB - Utf8 "(I)V"; // #26 at 0x0102 - Utf8 "Code"; // #27 at 0x0109 - Utf8 "LineNumberTable"; // #28 at 0x0110 - Utf8 "MethodParameters"; // #29 at 0x0122 - Utf8 "()Ljava/lang/String;"; // #30 at 0x0135 - Utf8 "()I"; // #31 at 0x014C - Utf8 "(Ljava/lang/Object;)Z"; // #32 at 0x0152 - Utf8 "SourceFile"; // #33 at 0x016A - Utf8 "recordIgnoredVersion.java"; // #34 at 0x0177 - Utf8 "Record"; // #35 at 0x018C - Utf8 "BootstrapMethods"; // #36 at 0x0195 - MethodHandle 6b #38; // #37 at 0x01A8 - Method #39 #40; // #38 at 0x01AC - class #41; // #39 at 0x01B1 - NameAndType #42 #43; // #40 at 0x01B4 - Utf8 "java/lang/runtime/ObjectMethods"; // #41 at 0x01B9 - Utf8 "bootstrap"; // #42 at 0x01DB - Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;"; // #43 at 0x01E7 - String #11; // #44 at 0x029B - MethodHandle 1b #7; // #45 at 0x029E - Utf8 "InnerClasses"; // #46 at 0x02A2 - class #48; // #47 at 0x02B1 - Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #48 at 0x02B4 - class #50; // #49 at 0x02DC - Utf8 "java/lang/invoke/MethodHandles"; // #50 at 0x02DF - Utf8 "Lookup"; // #51 at 0x0300 - } // Constant Pool - - 0x0030; // access [ ACC_SUPER ACC_FINAL ] - #8;// this_cpx - #2;// super_cpx - - [0] { // Interfaces - } // Interfaces - - [1] { // fields - { // Member at 0x0313 - 0x8012; // access - #11; // name_cpx - #12; // sig_cpx - [0] { // Attributes - } // Attributes - } // Member - } // fields - - [5] { // methods - { // Member at 0x031D - 0x0001; // access - #5; // name_cpx - #26; // sig_cpx - [2] { // Attributes - Attr(#27, 34) { // Code at 0x0325 - 2; // max_stack - 2; // max_locals - Bytes[10]{ - 0x2AB700012A1BB500; - 0x07B1; - } - [0] { // Traps - } // end Traps - [1] { // Attributes - Attr(#28, 6) { // LineNumberTable at 0x0341 - [1] { // LineNumberTable - 0 1; // at 0x034D - } - } // end LineNumberTable - } // Attributes - } // end Code - ; - Attr(#29, 5) { // MethodParameters at 0x034D - 0x01000B8000; - } // end MethodParameters - } // Attributes - } // Member - ; - { // Member at 0x0358 - 0x8001; // access - #16; // name_cpx - #30; // sig_cpx - [1] { // Attributes - Attr(#27, 31) { // Code at 0x0360 - 1; // max_stack - 1; // max_locals - Bytes[7]{ - 0x2ABA000E0000B0; - } - [0] { // Traps - } // end Traps - [1] { // Attributes - Attr(#28, 6) { // LineNumberTable at 0x0379 - [1] { // LineNumberTable - 0 1; // at 0x0385 - } - } // end LineNumberTable - } // Attributes - } // end Code - } // Attributes - } // Member - ; - { // Member at 0x0385 - 0x8011; // access - #20; // name_cpx - #31; // sig_cpx - [1] { // Attributes - Attr(#27, 31) { // Code at 0x038D - 1; // max_stack - 1; // max_locals - Bytes[7]{ - 0x2ABA00120000AC; - } - [0] { // Traps - } // end Traps - [1] { // Attributes - Attr(#28, 6) { // LineNumberTable at 0x03A6 - [1] { // LineNumberTable - 0 1; // at 0x03B2 - } - } // end LineNumberTable - } // Attributes - } // end Code - } // Attributes - } // Member - ; - { // Member at 0x03B2 - 0x8011; // access - #24; // name_cpx - #32; // sig_cpx - [1] { // Attributes - Attr(#27, 32) { // Code at 0x03BA - 2; // max_stack - 2; // max_locals - Bytes[8]{ - 0x2A2BBA00160000AC; - } - [0] { // Traps - } // end Traps - [1] { // Attributes - Attr(#28, 6) { // LineNumberTable at 0x03D4 - [1] { // LineNumberTable - 0 1; // at 0x03E0 - } - } // end LineNumberTable - } // Attributes - } // end Code - } // Attributes - } // Member - ; - { // Member at 0x03E0 - 0x8001; // access - #11; // name_cpx - #31; // sig_cpx - [1] { // Attributes - Attr(#27, 29) { // Code at 0x03E8 - 1; // max_stack - 1; // max_locals - Bytes[5]{ - 0x2AB4000DAC; - } - [0] { // Traps - } // end Traps - [1] { // Attributes - Attr(#28, 6) { // LineNumberTable at 0x03FF - [1] { // LineNumberTable - 0 1; // at 0x040B - } - } // end LineNumberTable - } // Attributes - } // end Code - } // Attributes - } // Member - } // methods - - [4] { // Attributes - Attr(#33, 2) { // SourceFile at 0x040D - #34; - } // end SourceFile - ; - Attr(#35, 8) { // Record at 0x0415 - 0x0001000B000C0000; - } // end Record - ; - Attr(#36, 12) { // BootstrapMethods at 0x0423 - [1] { // bootstrap_methods - { // bootstrap_method - #37; // bootstrap_method_ref - [3] { // bootstrap_arguments - #8; // at 0x0431 - #44; // at 0x0433 - #45; // at 0x0435 - } // bootstrap_arguments - } // bootstrap_method - } - } // end BootstrapMethods - ; - Attr(#46, 10) { // InnerClasses at 0x0435 - [1] { // InnerClasses - #47 #49 #51 25; // at 0x0445 - } - } // end InnerClasses - } // Attributes -} // end class recordIgnoredVersion diff --git a/test/hotspot/jtreg/runtime/records/recordReflectionTest.java b/test/hotspot/jtreg/runtime/records/recordReflectionTest.java index bf7f6f5a151..e731398c479 100644 --- a/test/hotspot/jtreg/runtime/records/recordReflectionTest.java +++ b/test/hotspot/jtreg/runtime/records/recordReflectionTest.java @@ -23,8 +23,8 @@ /* * @test - * @compile --enable-preview --source ${jdk.version} recordReflectionTest.java - * @run main/othervm --enable-preview recordReflectionTest + * @bug 8246774 + * @summary testing reflection APIs for record classes */ diff --git a/test/hotspot/jtreg/runtime/records/shortRecordAttribute.jcod b/test/hotspot/jtreg/runtime/records/shortRecordAttribute.jcod index 595cdf38acc..278900dc842 100644 --- a/test/hotspot/jtreg/runtime/records/shortRecordAttribute.jcod +++ b/test/hotspot/jtreg/runtime/records/shortRecordAttribute.jcod @@ -28,7 +28,7 @@ // attribute_count field. It should result in a ClassFormatError exception. class shortRecordAttribute { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty diff --git a/test/hotspot/jtreg/runtime/records/superNotJLRecord.jcod b/test/hotspot/jtreg/runtime/records/superNotJLRecord.jcod index 3e279ffec52..770907e8286 100644 --- a/test/hotspot/jtreg/runtime/records/superNotJLRecord.jcod +++ b/test/hotspot/jtreg/runtime/records/superNotJLRecord.jcod @@ -24,11 +24,12 @@ // This test was generated from this source and then modified: // record recordNames(int x, String y) {} -// This test has a Record attribute that is too short but its super class is -// not java.lang.Record. So, the bogus Record attribute should be ignored. +// This test has a Record attribute that is too short and its super class is +// not java.lang.Record. The bad Record attribute should still be detected +// causing a ClassFormatError exception. class superNotJLRecord { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty @@ -343,3 +344,329 @@ class superNotJLRecord { } // end Record } // Attributes } // end class superNotJLRecord + + + +// This test was generated from this source and then modified: +// record recordNames(int x, String y) {} +// +// This class has a valid Record attribute but its super class is +// not java.lang.Record. Loading this class should not cause a +// ClassFormatError exception. +class superNotJLRecordOK { + 0xCAFEBABE; + 0; // minor version + 60; // version + [69] { // Constant Pool + ; // first element is empty + Method #2 #3; // #1 at 0x0A + class #4; // #2 at 0x0F + NameAndType #5 #6; // #3 at 0x12 + Utf8 "java/lang/Object"; // #4 at 0x17 + Utf8 ""; // #5 at 0x2A + Utf8 "()V"; // #6 at 0x33 + Field #8 #9; // #7 at 0x39 + class #10; // #8 at 0x3E + NameAndType #11 #12; // #9 at 0x41 + Utf8 "superNotJLRecordOK"; // #10 at 0x46 + Utf8 "x"; // #11 at 0x56 + Utf8 "I"; // #12 at 0x5A + Field #8 #14; // #13 at 0x5E + NameAndType #15 #16; // #14 at 0x63 + Utf8 "y"; // #15 at 0x68 + Utf8 "Ljava/lang/String;"; // #16 at 0x6C + InvokeDynamic 0s #18; // #17 at 0x81 + NameAndType #19 #20; // #18 at 0x86 + Utf8 "toString"; // #19 at 0x8B + Utf8 "(LsuperNotJLRecordOK;)Ljava/lang/String;"; // #20 at 0x96 + InvokeDynamic 0s #22; // #21 at 0xBC + NameAndType #23 #24; // #22 at 0xC1 + Utf8 "hashCode"; // #23 at 0xC6 + Utf8 "(LsuperNotJLRecordOK;)I"; // #24 at 0xD1 + InvokeDynamic 0s #26; // #25 at 0xE6 + NameAndType #27 #28; // #26 at 0xEB + Utf8 "equals"; // #27 at 0xF0 + Utf8 "(LsuperNotJLRecordOK;Ljava/lang/Object;)Z"; // #28 at 0xF9 + Dynamic 1s #30; // #29 at 0x0120 + NameAndType #31 #32; // #30 at 0x0125 + Utf8 "\\%pattern\\%recordExample\\%(ILjava\\|lang\\|String\\?)"; // #31 at 0x012A + Utf8 "Ljava/lang/runtime/PatternHandle;"; // #32 at 0x015F + Utf8 "(ILjava/lang/String;)V"; // #33 at 0x0183 + Utf8 "Code"; // #34 at 0x019C + Utf8 "LineNumberTable"; // #35 at 0x01A3 + Utf8 "MethodParameters"; // #36 at 0x01B5 + Utf8 "()Ljava/lang/String;"; // #37 at 0x01C8 + Utf8 "()I"; // #38 at 0x01DF + Utf8 "(Ljava/lang/Object;)Z"; // #39 at 0x01E5 + Utf8 "()Ljava/lang/runtime/PatternHandle;"; // #40 at 0x01FD + Utf8 "SourceFile"; // #41 at 0x0223 + Utf8 "superNotJLRecordOK.java"; // #42 at 0x0230 + Utf8 "Record"; // #43 at 0x0245 + Utf8 "BootstrapMethods"; // #44 at 0x024E + MethodHandle 6b #46; // #45 at 0x0261 + Method #47 #48; // #46 at 0x0265 + class #49; // #47 at 0x026A + NameAndType #50 #51; // #48 at 0x026D + Utf8 "java/lang/runtime/ObjectMethods"; // #49 at 0x0272 + Utf8 "bootstrap"; // #50 at 0x029A + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;"; // #51 at 0x02A6 + String #53; // #52 at 0x035A + Utf8 "x;y"; // #53 at 0x035D + MethodHandle 1b #7; // #54 at 0x0363 + MethodHandle 1b #13; // #55 at 0x0367 + MethodHandle 6b #57; // #56 at 0x036B + Method #58 #59; // #57 at 0x036F + class #60; // #58 at 0x0374 + NameAndType #61 #62; // #59 at 0x0377 + Utf8 "java/lang/runtime/PatternHandles"; // #60 at 0x037C + Utf8 "ofLazyProjection"; // #61 at 0x039F + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/runtime/PatternHandle;"; // #62 at 0x03B2 + Utf8 "InnerClasses"; // #63 at 0x0453 + class #65; // #64 at 0x0462 + Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #65 at 0x0465 + class #67; // #66 at 0x048D + Utf8 "java/lang/invoke/MethodHandles"; // #67 at 0x0490 + Utf8 "Lookup"; // #68 at 0x04B1 + } // Constant Pool + + 0x0030; // access [ ACC_SUPER ACC_FINAL ] + #8;// this_cpx + #2;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [2] { // fields + { // Member at 0x04C4 + 0x8012; // access + #11; // name_cpx + #12; // sig_cpx + [0] { // Attributes + } // Attributes + } // Member + ; + { // Member at 0x04CC + 0x8012; // access + #15; // name_cpx + #16; // sig_cpx + [0] { // Attributes + } // Attributes + } // Member + } // fields + + [7] { // methods + { // Member at 0x04D6 + 0x0001; // access + #5; // name_cpx + #33; // sig_cpx + [2] { // Attributes + Attr(#34, 39) { // Code at 0x04DE + 2; // max_stack + 3; // max_locals + Bytes[15]{ + 0x2AB700012A1BB500; + 0x072A2CB5000DB1; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x04FF + [1] { // LineNumberTable + 0 1; // at 0x050B + } + } // end LineNumberTable + } // Attributes + } // end Code + ; + Attr(#36, 9) { // MethodParameters at 0x050B + 0x02000B8000000F80; + 0x00; + } // end MethodParameters + } // Attributes + } // Member + ; + { // Member at 0x051A + 0x8001; // access + #19; // name_cpx + #37; // sig_cpx + [1] { // Attributes + Attr(#34, 31) { // Code at 0x0522 + 1; // max_stack + 1; // max_locals + Bytes[7]{ + 0x2ABA00110000B0; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x053B + [1] { // LineNumberTable + 0 1; // at 0x0547 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0547 + 0x8011; // access + #23; // name_cpx + #38; // sig_cpx + [1] { // Attributes + Attr(#34, 31) { // Code at 0x054F + 1; // max_stack + 1; // max_locals + Bytes[7]{ + 0x2ABA00150000AC; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0568 + [1] { // LineNumberTable + 0 1; // at 0x0574 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0574 + 0x8011; // access + #27; // name_cpx + #39; // sig_cpx + [1] { // Attributes + Attr(#34, 32) { // Code at 0x057C + 2; // max_stack + 2; // max_locals + Bytes[8]{ + 0x2A2BBA00190000AC; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0596 + [1] { // LineNumberTable + 0 1; // at 0x05A2 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x05A2 + 0x8001; // access + #11; // name_cpx + #38; // sig_cpx + [1] { // Attributes + Attr(#34, 29) { // Code at 0x05AA + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB40007AC; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x05C1 + [1] { // LineNumberTable + 0 1; // at 0x05CD + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x05CD + 0x8001; // access + #15; // name_cpx + #37; // sig_cpx + [1] { // Attributes + Attr(#34, 29) { // Code at 0x05D5 + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB4000DB0; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x05EC + [1] { // LineNumberTable + 0 1; // at 0x05F8 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x05F8 + 0x0009; // access + #31; // name_cpx + #40; // sig_cpx + [1] { // Attributes + Attr(#34, 27) { // Code at 0x0600 + 1; // max_stack + 0; // max_locals + Bytes[3]{ + 0x121DB0; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0615 + [1] { // LineNumberTable + 0 1; // at 0x0621 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [4] { // Attributes + Attr(#41, 2) { // SourceFile at 0x0623 + #42; + } // end SourceFile + ; + Attr(#43, 14) { // Record at 0x062B + 0x0002000B000C0000; + 0x000F00100000; + } // end Record + ; + Attr(#44, 24) { // BootstrapMethods at 0x063F + [2] { // bootstrap_methods + { // bootstrap_method + #45; // bootstrap_method_ref + [4] { // bootstrap_arguments + #8; // at 0x064D + #52; // at 0x064F + #54; // at 0x0651 + #55; // at 0x0653 + } // bootstrap_arguments + } // bootstrap_method + ; + { // bootstrap_method + #56; // bootstrap_method_ref + [3] { // bootstrap_arguments + #8; // at 0x0659 + #54; // at 0x065B + #55; // at 0x065D + } // bootstrap_arguments + } // bootstrap_method + } + } // end BootstrapMethods + ; + Attr(#63, 10) { // InnerClasses at 0x065D + [1] { // InnerClasses + #64 #66 #68 25; // at 0x066D + } + } // end InnerClasses + } // Attributes +} // end class superNotJLRecordOK diff --git a/test/hotspot/jtreg/runtime/records/twoRecordAttributes.jcod b/test/hotspot/jtreg/runtime/records/twoRecordAttributes.jcod index 4a7ef78ee69..72e0b4ad2d2 100644 --- a/test/hotspot/jtreg/runtime/records/twoRecordAttributes.jcod +++ b/test/hotspot/jtreg/runtime/records/twoRecordAttributes.jcod @@ -28,7 +28,7 @@ // a ClassFormatError exception. class twoRecordAttributes { 0xCAFEBABE; - 65535; // minor version + 0; // minor version 60; // version [69] { // Constant Pool ; // first element is empty diff --git a/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java b/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java index d90012d0fba..3d36d868115 100644 --- a/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java +++ b/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ public static void main(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", "Overrider"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain( - "java.lang.VerifyError: class Overrider overrides final method HasFinal.m(Ljava/lang/String;)V"); + "java.lang.IncompatibleClassChangeError: class Overrider overrides final method HasFinal.m(Ljava/lang/String;)V"); output.shouldHaveExitValue(1); } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/finalSuperclass/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/finalSuperclass/TestDescription.java index 19a83c1120c..e6142ebe396 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/finalSuperclass/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/finalSuperclass/TestDescription.java @@ -30,9 +30,9 @@ * VM Testbase keywords: [feature_mlvm] * VM Testbase readme: * DESCRIPTION - * Try to load anonymous class derived from java.lang.System. The verification - * system (split verifier and system class loader) should reject such attempt and - * throw VerifyError. + * Try to load anonymous class derived from java.lang.System. The class file + * loader should reject such attempt and throw IncompatibleClassChangeError + * because java.lang.System is a final class. * * @library /vmTestbase * /test/lib @@ -44,6 +44,6 @@ * @run main/othervm * vm.mlvm.anonloader.share.ReplaceClassParentTest * -newParent java/lang/System - * -requireExceptions java.lang.VerifyError + * -requireExceptions java.lang.IncompatibleClassChangeError */ diff --git a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ObjectMethodOverridesTest.java b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ObjectMethodOverridesTest.java index 61564d07380..9858449bb1b 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ObjectMethodOverridesTest.java +++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ObjectMethodOverridesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,7 +123,7 @@ public void testGetClass() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } @@ -158,7 +158,7 @@ public void testNotify() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } @@ -174,7 +174,7 @@ public void testNotifyAll() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } @@ -208,7 +208,7 @@ public void testWait() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } @@ -224,7 +224,7 @@ public void testTimedWait() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } @@ -240,7 +240,7 @@ public void testTimedWait1() throws Exception { ConcreteClass C = b.clazz("C").implement(I).build(); - b.test().loadClass(I).throws_(VerifyError.class).done() + b.test().loadClass(I).throws_(IncompatibleClassChangeError.class).done() .run(); } } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 0b617068b33..fca80aac41e 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -560,6 +560,7 @@ java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all # jdk_foreign java/foreign/TestMismatch.java 8249684 macosx-all +java/foreign/TestMismatch.java 8255270 generic-i586 ############################################################################ @@ -759,7 +760,6 @@ javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all javax/swing/JPopupMenu/6675802/bug6675802.java 8196097 windows-all javax/swing/JTabbedPane/8007563/Test8007563.java 8051591 generic-all javax/swing/JTabbedPane/4624207/bug4624207.java 8064922 macosx-all -javax/swing/JTabbedPane/7024235/Test7024235.java 8028281 macosx-all javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all javax/swing/plaf/basic/Test6984643.java 8198340 windows-all javax/swing/text/CSSBorder/6796710/bug6796710.java 8196099 windows-all @@ -775,44 +775,25 @@ javax/swing/JInternalFrame/Test6325652.java 8224977 macosx-all javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java 8225045 linux-all javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all javax/swing/JFileChooser/6868611/bug6868611.java 7059834 windows-all -javax/swing/SwingWorker/6493680/bug6493680.java 8198410 windows-all javax/swing/PopupFactory/6276087/NonOpaquePopupMenuTest.java 8065099,8208565 macosx-all,linux-all -javax/swing/DataTransfer/8059739/bug8059739.java 8199074 generic-all -javax/swing/SwingWorker/6432565/bug6432565.java 8199077 generic-all -javax/swing/SwingWorker/6880336/NestedWorkers.java 8199049 windows-all -javax/swing/text/DefaultCaret/6938583/bug6938583.java 8199058 generic-all -javax/swing/text/html/parser/Parser/6990651/bug6990651.java 8199060 generic-all -javax/swing/text/html/parser/Parser/HtmlCommentTagParseTest/HtmlCommentTagParseTest.java 8199073 generic-all -javax/swing/text/StyledEditorKit/8016833/bug8016833.java 8199055 generic-all -javax/swing/text/Utilities/8134721/bug8134721.java 8199062 generic-all -javax/swing/tree/DefaultTreeCellRenderer/7142955/bug7142955.java 8199076 generic-all javax/swing/UIDefaults/6302464/bug6302464.java 8199079 macosx-all -javax/swing/UIDefaults/8149879/InternalResourceBundle.java 8199054 windows-all javax/swing/PopupFactory/8048506/bug8048506.java 8202660 windows-all -javax/swing/JTextArea/TextViewOOM/TextViewOOM.java 8167355 generic-all javax/swing/JPopupMenu/8075063/ContextMenuScrollTest.java 202880 linux-all javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all javax/swing/Popup/TaskbarPositionTest.java 8065097 macosx-all,linux-all javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all javax/swing/JTree/6263446/bug6263446.java 8213125 macosx-all -javax/swing/ToolTipManager/Test6256140.java 8233560 macosx-all javax/swing/text/View/8014863/bug8014863.java 8233561 macosx-all javax/swing/text/StyledEditorKit/4506788/bug4506788.java 8233562 macosx-all javax/swing/text/JTextComponent/6361367/bug6361367.java 8233569 macosx-all -javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java 233570 macosx-all javax/swing/JRootPane/4670486/bug4670486.java 8042381 macosx-all javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java 8233555 macosx-all javax/swing/JRadioButton/8075609/bug8075609.java 8233555 macosx-all javax/swing/JRadioButton/8033699/bug8033699.java 8233555 macosx-all -javax/swing/JPopupMenu/6827786/bug6827786.java 8233556 macosx-all -javax/swing/JPopupMenu/6544309/bug6544309.java 8233556 macosx-all -javax/swing/JPopupMenu/4634626/bug4634626.java 8233556 macosx-all -javax/swing/JPopupMenu/4458079/bug4458079.java 8233556 macosx-all +javax/swing/JPopupMenu/4634626/bug4634626.java 8017175 macosx-all javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java 8233637 macosx-all javax/swing/JMenuItem/6249972/bug6249972.java 8233640 macosx-all javax/swing/JMenuItem/4171437/bug4171437.java 8233641 macosx-all -javax/swing/JMenu/4692443/bug4692443.java 8171998 macosx-all -javax/swing/plaf/basic/BasicComboPopup/JComboBoxPopupLocation/JComboBoxPopupLocation.java 8238720 windows-all sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all @@ -890,3 +871,32 @@ jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows- tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java#id0 8248418 generic-all ############################################################################ + +# Client manual tests + +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_1.java 7131438,8022539 generic-all +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,8022539 generic-all +java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all +java/awt/Component/UpdatingBootTime/UpdatingBootTime.html 7194219 linux-all +java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all +java/awt/TextArea/MouseOverScrollbarWhenTyping/Test1.java 8005970 macosx-all,windows-all +javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all +javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all +java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all +java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.html 8080185 macosx-all,linux-all +javax/swing/JTabbedPane/4666224/bug4666224.html 8144124 macosx-all +java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java 8162380 generic-all +java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java 8163086 macosx-all +java/awt/image/multiresolution/MultiResolutionIcon/IconTest.java 8250804 macosx-all,linux-all +java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all +java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all +java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java 8185429 macosx-all +java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html 8203867 macosx-all +java/awt/Frame/FrameStateTest/FrameStateTest.html 8203920 macosx-all,linux-all +javax/swing/SwingUtilities/TestTextPosInPrint.java 8227025 windows-all +java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all +java/awt/font/TextLayout/TestJustification.html 8250791 macosx-all +javax/swing/JTabbedPane/4209065/bug4209065.java 8251177 macosx-all +java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all + +############################################################################ diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 71a3d4795c6..ab63cc78ef6 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -58,7 +58,8 @@ requires.properties= \ vm.hasJFR \ vm.jvmci \ docker.support \ - release.implementor + release.implementor \ + jdk.containerized # Minimum jtreg version requiredVersion=5.1 b1 diff --git a/test/jdk/com/sun/jdi/BadHandshakeTest.java b/test/jdk/com/sun/jdi/BadHandshakeTest.java index 40bac30561d..f2b975ecfcc 100644 --- a/test/jdk/com/sun/jdi/BadHandshakeTest.java +++ b/test/jdk/com/sun/jdi/BadHandshakeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,28 +112,51 @@ public static void main(String args[]) throws Exception { throw error; } - log("cleaning..."); - // Attach to server debuggee and resume it so it can exit + log("final attach..."); + // Attach to server debuggee to ensure it's still available to attach and resume it so it can exit AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach"); - Map conn_args = conn.defaultArguments(); - Connector.IntegerArgument port_arg = - (Connector.IntegerArgument)conn_args.get("port"); - port_arg.setValue(port); - VirtualMachine vm = conn.attach(conn_args); + retryDelay = 20; + for (int retry = 0; retry < 5; retry++) { + if (error != null) { + try { + Thread.sleep(retryDelay); + } catch (InterruptedException ex) { + // ignore + } + retryDelay *= 2; + error = null; + } + try { + log("retry: " + retry); + Map conn_args = conn.defaultArguments(); + Connector.IntegerArgument port_arg = + (Connector.IntegerArgument)conn_args.get("port"); + port_arg.setValue(port); + VirtualMachine vm = conn.attach(conn_args); + + // The first event is always a VMStartEvent, and it is always in + // an EventSet by itself. Wait for it. + EventSet evtSet = vm.eventQueue().remove(); + for (Event event : evtSet) { + if (event instanceof VMStartEvent) { + break; + } + throw new RuntimeException("Test failed - debuggee did not start properly"); + } - // The first event is always a VMStartEvent, and it is always in - // an EventSet by itself. Wait for it. - EventSet evtSet = vm.eventQueue().remove(); - for (Event event : evtSet) { - if (event instanceof VMStartEvent) { + vm.eventRequestManager().deleteAllBreakpoints(); + vm.resume(); break; + } catch (ConnectException ex) { + log("got exception: " + ex.toString()); + error = ex; } - throw new RuntimeException("Test failed - debuggee did not start properly"); + } + if (error != null) { + throw error; } - vm.eventRequestManager().deleteAllBreakpoints(); - vm.resume(); - + // give the debuggee some time to exit before forcibly terminating it debuggee.waitFor(10, TimeUnit.SECONDS); } } diff --git a/test/jdk/java/awt/Choice/GetSizeTest/GetSizeTest.java b/test/jdk/java/awt/Choice/GetSizeTest/GetSizeTest.java index 54bb22ccd9e..b44106a28db 100644 --- a/test/jdk/java/awt/Choice/GetSizeTest/GetSizeTest.java +++ b/test/jdk/java/awt/Choice/GetSizeTest/GetSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,14 @@ run main GetSizeTest.html */ -import java.awt.*; -import java.awt.event.*; +import java.awt.Choice; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; public class GetSizeTest { @@ -40,16 +46,15 @@ public class GetSizeTest { "what choices do I have?", "Will I pick the same thing in the future?", }; - static boolean passed = false; - static Robot robot = null; + static volatile boolean passed = false; - public static void main(String args[]) - { + public static void main(String args[]) throws Exception { + Frame f = null; try { - robot = new Robot(); - robot.setAutoDelay(50); + Robot robot = new Robot(); + robot.setAutoDelay(150); - Frame f = new Frame("choice test"); + f = new Frame("choice test"); Panel p = new Panel(); p.setLayout(null); @@ -70,14 +75,7 @@ public void mouseReleased(MouseEvent e) { f.add(p); f.setSize(300, 300); - - f.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent we) { - System.err.println("Test passed"); - passed = true; - } - }); - + f.setLocationRelativeTo(null); f.setVisible(true); c.setSize(200, 200); @@ -88,14 +86,13 @@ public void windowClosing(WindowEvent we) { Point pt = c.getLocationOnScreen(); robot.mouseMove(pt.x + c.getWidth() - 10, pt.y + c.getHeight() / 2); robot.waitForIdle(); - robot.mousePress(InputEvent.BUTTON2_MASK); - robot.mouseRelease(InputEvent.BUTTON2_MASK); + robot.mousePress(InputEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK); robot.waitForIdle(); - } catch (Throwable e) { - if (robot == null){ - throw new RuntimeException( "Test failed.Unable to initialize Robot "+e); + } finally { + if (f != null) { + f.dispose(); } - throw new RuntimeException( "Test failed due to thrown exception "+e); } if (!passed) { throw new RuntimeException( "Timeout. Choice component size is not actual size." ); diff --git a/test/jdk/java/awt/color/ICC_ProfileGrayTest.java b/test/jdk/java/awt/color/ICC_ProfileGrayTest.java new file mode 100644 index 00000000000..471d108af48 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_ProfileGrayTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileGray; +import java.awt.color.ProfileDataException; + +/** + * @test + * @bug 8254370 + * @summary Tests basic ICC_ProfileGray functionality + */ +public final class ICC_ProfileGrayTest { + + public static void main(String[] args) throws Exception { + ICC_Profile csProfile = ICC_Profile.getInstance(ColorSpace.CS_GRAY); + ICC_Profile dataProfile = ICC_Profile.getInstance(csProfile.getData()); + ICC_Profile stringProfile = ICC_Profile.getInstance("GRAY.pf"); + test(csProfile); + test(dataProfile); + test(stringProfile); + } + + private static void test(ICC_Profile profile) { + // Gray profile should be implemented as ICC_ProfileGray and includes + // the mediaWhitePointTag and grayTRCTag tags + if (!(profile instanceof ICC_ProfileGray) + || profile.getData(ICC_Profile.icSigMediaWhitePointTag) == null + || profile.getData(ICC_Profile.icSigGrayTRCTag) == null) { + throw new RuntimeException("Wrong profile: " + profile); + } + + ICC_ProfileGray gray = (ICC_ProfileGray) profile; + + int length = gray.getMediaWhitePoint().length; + if (length != 3) { + throw new RuntimeException("Wrong data length: " + length); + } + + // if getTRC() throws an exception then getGamma() should work + boolean trc = false; + try { + gray.getTRC(); + trc = true; + System.out.println("getTRC() works fine"); + } catch (ProfileDataException ignore) { + gray.getGamma(); + } + // if getGamma() throws an exception then getTRC() should work + boolean gamma = false; + try { + gray.getGamma(); + gamma = true; + System.out.println("getGamma() works fine"); + } catch (ProfileDataException ignore) { + gray.getTRC(); + } + + if (gamma == trc) { + // only one should work + throw new RuntimeException("Only one operation should work"); + } + } +} diff --git a/test/jdk/java/awt/color/ICC_ProfileRGBTest.java b/test/jdk/java/awt/color/ICC_ProfileRGBTest.java new file mode 100644 index 00000000000..a1b2562d33e --- /dev/null +++ b/test/jdk/java/awt/color/ICC_ProfileRGBTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileRGB; +import java.awt.color.ProfileDataException; +import java.util.Arrays; + +/** + * @test + * @bug 8254370 + * @summary Tests basic ICC_ProfileRGB functionality + */ +public final class ICC_ProfileRGBTest { + + public static void main(String[] args) throws Exception { + ICC_Profile csProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB); + ICC_Profile dataProfile = ICC_Profile.getInstance(csProfile.getData()); + ICC_Profile string2Profile = ICC_Profile.getInstance("sRGB.pf"); + ICC_Profile string1Profile = ICC_Profile.getInstance("LINEAR_RGB.pf"); + test(csProfile); + test(dataProfile); + test(string1Profile); + test(string2Profile); + } + + private static void test(ICC_Profile profile) { + // RGB profile should be implemented as ICC_ProfileRGB and includes the + // redColorantTag, greenColorantTag, blueColorantTag, redTRCTag, + // greenTRCTag, blueTRCTag, mediaWhitePointTag tags + if (!(profile instanceof ICC_ProfileRGB) + || profile.getData(ICC_Profile.icSigRedColorantTag) == null + || profile.getData(ICC_Profile.icSigGreenColorantTag) == null + || profile.getData(ICC_Profile.icSigBlueColorantTag) == null + || profile.getData(ICC_Profile.icSigRedTRCTag) == null + || profile.getData(ICC_Profile.icSigGreenTRCTag) == null + || profile.getData(ICC_Profile.icSigBlueTRCTag) == null + || profile.getData(ICC_Profile.icSigMediaWhitePointTag) == null) + { + throw new RuntimeException("Wrong profile: " + profile); + } + + ICC_ProfileRGB rgb = (ICC_ProfileRGB) profile; + + int length = rgb.getMediaWhitePoint().length; + if (length != 3) { + throw new RuntimeException("Wrong data length: " + length); + } + + // if getTRC() throws an exception then getGamma() should work + boolean trc = false; + try { + rgb.getTRC(ICC_ProfileRGB.REDCOMPONENT); + rgb.getTRC(ICC_ProfileRGB.GREENCOMPONENT); + rgb.getTRC(ICC_ProfileRGB.BLUECOMPONENT); + trc = true; + System.out.println("getTRC() works fine"); + } catch (ProfileDataException ignore) { + rgb.getGamma(ICC_ProfileRGB.REDCOMPONENT); + rgb.getGamma(ICC_ProfileRGB.GREENCOMPONENT); + rgb.getGamma(ICC_ProfileRGB.BLUECOMPONENT); + } + // if getGamma() throws an exception then getTRC() should work + boolean gamma = false; + try { + rgb.getGamma(ICC_ProfileRGB.REDCOMPONENT); + rgb.getGamma(ICC_ProfileRGB.GREENCOMPONENT); + rgb.getGamma(ICC_ProfileRGB.BLUECOMPONENT); + gamma = true; + System.out.println("getGamma() works fine"); + } catch (ProfileDataException ignore) { + rgb.getTRC(ICC_ProfileRGB.REDCOMPONENT); + rgb.getTRC(ICC_ProfileRGB.GREENCOMPONENT); + rgb.getTRC(ICC_ProfileRGB.BLUECOMPONENT); + } + + if (gamma == trc) { + // only one should work fine + throw new RuntimeException("Only one operation should work"); + } + + // IllegalArgumentException if the component is invalid + try { + rgb.getGamma(10); + throw new RuntimeException("IllegalArgumentException was expected"); + } catch (IllegalArgumentException ignored) {} + try { + rgb.getGamma(-1); + throw new RuntimeException("IllegalArgumentException was expected"); + } catch (IllegalArgumentException ignored) {} + try { + rgb.getTRC(10); + throw new RuntimeException("IllegalArgumentException was expected"); + } catch (IllegalArgumentException ignored) {} + try { + rgb.getTRC(-1); + throw new RuntimeException("IllegalArgumentException was expected"); + } catch (IllegalArgumentException ignored) {} + + // Validates content of ICC_ProfileRGB.getMatrix() + float[][] matrix = rgb.getMatrix(); // current implementation + float[][] old = getMatrix(rgb); // old implementation + if (!Arrays.deepEquals(matrix, old)) { + System.err.println("Expected: " + Arrays.deepToString(old)); + System.err.println("Actual: " + Arrays.deepToString(matrix)); + throw new RuntimeException("Wrong matrix"); + } + } + + /** + * Old implementation of ICC_ProfileRGB.getMatrix(). + */ + private static float[][] getMatrix(ICC_ProfileRGB profile) { + float[] tmpMatrix = getXYZTag(profile, ICC_Profile.icSigRedColorantTag); + float[][] theMatrix = new float[3][3]; + theMatrix[0][0] = tmpMatrix[0]; + theMatrix[1][0] = tmpMatrix[1]; + theMatrix[2][0] = tmpMatrix[2]; + tmpMatrix = getXYZTag(profile, ICC_Profile.icSigGreenColorantTag); + theMatrix[0][1] = tmpMatrix[0]; + theMatrix[1][1] = tmpMatrix[1]; + theMatrix[2][1] = tmpMatrix[2]; + tmpMatrix = getXYZTag(profile, ICC_Profile.icSigBlueColorantTag); + theMatrix[0][2] = tmpMatrix[0]; + theMatrix[1][2] = tmpMatrix[1]; + theMatrix[2][2] = tmpMatrix[2]; + return theMatrix; + } + + private static float[] getXYZTag(ICC_ProfileRGB profile, int theTagSignature) { + byte[] theData = profile.getData(theTagSignature); + float[] theXYZNumber = new float[3]; + for (int i1 = 0, i2 = profile.icXYZNumberX; i1 < 3; i1++, i2 += 4) { + int theS15Fixed16 = intFromBigEndian(theData, i2); + theXYZNumber [i1] = theS15Fixed16 / 65536.0f; + } + return theXYZNumber; + } + + static int intFromBigEndian(byte[] array, int index) { + return (((array[index] & 0xff) << 24) | + ((array[index+1] & 0xff) << 16) | + ((array[index+2] & 0xff) << 8) | + (array[index+3] & 0xff)); + } +} diff --git a/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java b/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java index 6cf79322c27..275f8ee446e 100644 --- a/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java +++ b/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ public void flavorsChanged(FlavorEvent e) { } }); - System.out.println("Starting external clipborad modifier..."); + System.out.println("Starting external clipboard modifier..."); new Thread(() -> runTest(ClipboardInterVMTest.class.getCanonicalName(), "pong")).start(); String content = ""; @@ -106,7 +106,7 @@ public void flavorsChanged(FlavorEvent e) { }; if (!flavorChangedMonitor.await(10, TimeUnit.SECONDS)) { - throw new RuntimeException("No LostOwnership event received."); + throw new RuntimeException("No FlavorsChanged event received."); }; if (!content.equals("pong")) { diff --git a/test/jdk/java/awt/print/bug8023392/bug8023392.java b/test/jdk/java/awt/print/bug8023392/bug8023392.java index 9b7c6bc2313..440de96a061 100644 --- a/test/jdk/java/awt/print/bug8023392/bug8023392.java +++ b/test/jdk/java/awt/print/bug8023392/bug8023392.java @@ -46,6 +46,7 @@ public class bug8023392 extends Applet { static final String[] instructions = { + "Please select the RadioButton for applet size labeled \"variable\" radiobutton in test harness window.", "A Frame containing several pairs of labels ((a) and (b)) is displayed.", "Labels of each pair look the same and are left-aligned (with spaces ", "between chars).", @@ -169,7 +170,9 @@ public int print(Graphics graphics, if (pageIndex >= 1) { return Printable.NO_SUCH_PAGE; } - + double imgX = pageFormat.getImageableX(); + double imgY = pageFormat.getImageableY(); + ((Graphics2D)graphics).translate(imgX, imgY); this.paint(graphics); return Printable.PAGE_EXISTS; } diff --git a/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java b/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java index 2980b4e4063..153d0a6e995 100644 --- a/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java +++ b/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Checks that the appropriate default value is given to the canonical ctr - * @compile --enable-preview -source ${jdk.version} AbsentStreamValuesTest.java - * @run testng/othervm --enable-preview AbsentStreamValuesTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview AbsentStreamValuesTest + * @run testng AbsentStreamValuesTest + * @run testng/othervm/java.security.policy=empty_security.policy AbsentStreamValuesTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java index 4f57f97bf7e..8b0a1ae625b 100644 --- a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java +++ b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java @@ -23,12 +23,12 @@ /* * @test + * @bug 8246774 * @summary InvalidClassException is thrown when the canonical constructor * cannot be found during deserialization. * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm - * @compile --enable-preview -source ${jdk.version} BadCanonicalCtrTest.java - * @run testng/othervm --enable-preview BadCanonicalCtrTest + * @run testng BadCanonicalCtrTest */ import java.io.ByteArrayInputStream; @@ -59,7 +59,6 @@ * constructor cannot be found during deserialization. */ public class BadCanonicalCtrTest { - private static final String VERSION = Integer.toString(Runtime.version().feature()); // ClassLoader for creating instances of the records to test with. ClassLoader goodRecordClassLoader; @@ -79,8 +78,7 @@ public class BadCanonicalCtrTest { public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("R1", - "public record R1 () implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R1 () implements java.io.Serializable { }"); goodRecordClassLoader = new ByteCodeLoader("R1", byteCode, BadCanonicalCtrTest.class.getClassLoader()); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R1", bc1, BadCanonicalCtrTest.class.getClassLoader()); @@ -89,8 +87,7 @@ public void setup() { } { byte[] byteCode = InMemoryJavaCompiler.compile("R2", - "public record R2 (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R2 (int x, int y) implements java.io.Serializable { }"); goodRecordClassLoader = new ByteCodeLoader("R2", byteCode, goodRecordClassLoader); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R2", bc1, missingCtrClassLoader); @@ -101,8 +98,7 @@ public void setup() { byte[] byteCode = InMemoryJavaCompiler.compile("R3", "public record R3 (long l) implements java.io.Externalizable {" + " public void writeExternal(java.io.ObjectOutput out) { }" + - " public void readExternal(java.io.ObjectInput in) { } }", - "--enable-preview", "-source", VERSION); + " public void readExternal(java.io.ObjectInput in) { } }"); goodRecordClassLoader = new ByteCodeLoader("R3", byteCode, goodRecordClassLoader); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R3", bc1, missingCtrClassLoader); diff --git a/test/jdk/java/io/Serializable/records/BasicRecordSer.java b/test/jdk/java/io/Serializable/records/BasicRecordSer.java index 4454c804c4b..ee50f630351 100644 --- a/test/jdk/java/io/Serializable/records/BasicRecordSer.java +++ b/test/jdk/java/io/Serializable/records/BasicRecordSer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic test that serializes and deserializes a number of records - * @compile --enable-preview -source ${jdk.version} BasicRecordSer.java - * @run testng/othervm --enable-preview BasicRecordSer - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview BasicRecordSer + * @run testng BasicRecordSer + * @run testng/othervm/java.security.policy=empty_security.policy BasicRecordSer */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java b/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java index 9624e10987f..c9f2be0e18f 100644 --- a/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java +++ b/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,11 @@ /* * @test + * @bug 8246774 * @summary Ensures that the serialization implementation can *always* access * the record constructor - * @compile --enable-preview -source ${jdk.version} ConstructorAccessTest.java - * @run testng/othervm --enable-preview ConstructorAccessTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview ConstructorAccessTest + * @run testng ConstructorAccessTest + * @run testng/othervm/java.security.policy=empty_security.policy ConstructorAccessTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/ConstructorPermissionTest.java b/test/jdk/java/io/Serializable/records/ConstructorPermissionTest.java index d868fffec56..6b0109230b0 100644 --- a/test/jdk/java/io/Serializable/records/ConstructorPermissionTest.java +++ b/test/jdk/java/io/Serializable/records/ConstructorPermissionTest.java @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Verifies that privileged operations performed in the record * constructor throw, when run without the required permissions - * @compile --enable-preview -source ${jdk.version} ConstructorPermissionTest.java - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview ConstructorPermissionTest + * @run testng/othervm/java.security.policy=empty_security.policy ConstructorPermissionTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/CycleTest.java b/test/jdk/java/io/Serializable/records/CycleTest.java index 0933303b2ce..9df703c3bc1 100644 --- a/test/jdk/java/io/Serializable/records/CycleTest.java +++ b/test/jdk/java/io/Serializable/records/CycleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Ensures basic behavior of cycles from record components - * @compile --enable-preview -source ${jdk.version} CycleTest.java - * @run testng/othervm --enable-preview CycleTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview CycleTest + * @run testng CycleTest + * @run testng/othervm/java.security.policy=empty_security.policy CycleTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java index 1624dce6190..d4101f9894b 100644 --- a/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java @@ -23,11 +23,11 @@ /* * @test + * @bug 8246774 * @summary Checks that the appropriate value is given to the canonical ctr * @library /test/lib - * @compile --enable-preview -source ${jdk.version} DifferentStreamFieldsTest.java - * @run testng/othervm --enable-preview DifferentStreamFieldsTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview DifferentStreamFieldsTest + * @run testng DifferentStreamFieldsTest + * @run testng/othervm/java.security.policy=empty_security.policy DifferentStreamFieldsTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java index 4863a6054b3..099008b4306 100644 --- a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java +++ b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java @@ -23,11 +23,11 @@ /* * @test + * @bug 8246774 * @summary Basic tests for prohibited magic serialization methods * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm - * @compile --enable-preview -source ${jdk.version} ProhibitedMethods.java - * @run testng/othervm --enable-preview ProhibitedMethods + * @run testng ProhibitedMethods */ import java.io.ByteArrayInputStream; @@ -69,7 +69,6 @@ * record objects. */ public class ProhibitedMethods { - private static final String VERSION = Integer.toString(Runtime.version().feature()); public interface ThrowingExternalizable extends Externalizable { default void writeExternal(ObjectOutput out) { @@ -106,8 +105,7 @@ record Wubble (Wobble wobble, Wibble wibble, String s) implements ThrowingExtern public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("Foo", - "public record Foo () implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record Foo () implements java.io.Serializable { }"); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); @@ -115,8 +113,7 @@ public void setup() { } { byte[] byteCode = InMemoryJavaCompiler.compile("Bar", - "public record Bar (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record Bar (int x, int y) implements java.io.Serializable { }"); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); @@ -125,8 +122,7 @@ public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("Baz", "import java.io.Serializable;" + - "public record Baz(U u, V v) implements Serializable { }", - "--enable-preview", "-source", VERSION); + "public record Baz(U u, V v) implements Serializable { }"); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); diff --git a/test/jdk/java/io/Serializable/records/ReadResolveTest.java b/test/jdk/java/io/Serializable/records/ReadResolveTest.java index e5cc24c53c7..725f2cb49ea 100644 --- a/test/jdk/java/io/Serializable/records/ReadResolveTest.java +++ b/test/jdk/java/io/Serializable/records/ReadResolveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic tests for readResolve - * @compile --enable-preview -source ${jdk.version} ReadResolveTest.java - * @run testng/othervm --enable-preview ReadResolveTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview ReadResolveTest + * @run testng ReadResolveTest + * @run testng/othervm/java.security.policy=empty_security.policy ReadResolveTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/RecordClassTest.java b/test/jdk/java/io/Serializable/records/RecordClassTest.java index e101daccec1..6506f9f85e4 100644 --- a/test/jdk/java/io/Serializable/records/RecordClassTest.java +++ b/test/jdk/java/io/Serializable/records/RecordClassTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic tests for serializing and deserializing record classes - * @compile --enable-preview -source ${jdk.version} RecordClassTest.java - * @run testng/othervm --enable-preview RecordClassTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview RecordClassTest + * @run testng RecordClassTest + * @run testng/othervm/java.security.policy=empty_security.policy RecordClassTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java index 186275a201a..0d88074bdbc 100644 --- a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java @@ -23,11 +23,11 @@ /* * @test + * @bug 8246774 * @summary Basic tests for prohibited magic serialPersistentFields * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm - * @compile --enable-preview -source ${jdk.version} SerialPersistentFieldsTest.java - * @run testng/othervm --enable-preview SerialPersistentFieldsTest + * @run testng SerialPersistentFieldsTest */ import java.io.ByteArrayInputStream; @@ -62,7 +62,6 @@ * Checks that the serialPersistentFields declaration is effectively ignored. */ public class SerialPersistentFieldsTest { - private static final String VERSION = Integer.toString(Runtime.version().feature()); ClassLoader serializableRecordLoader; @@ -83,8 +82,7 @@ public class SerialPersistentFieldsTest { public void setup() { { // R1 byte[] byteCode = InMemoryJavaCompiler.compile("R1", - "public record R1 () implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R1 () implements java.io.Serializable { }"); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("s", String.class), new ObjectStreamField("i", int.class), @@ -96,8 +94,7 @@ public void setup() { } { // R2 byte[] byteCode = InMemoryJavaCompiler.compile("R2", - "public record R2 (int x) implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R2 (int x) implements java.io.Serializable { }"); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("s", String.class) }; @@ -106,8 +103,7 @@ public void setup() { } { // R3 byte[] byteCode = InMemoryJavaCompiler.compile("R3", - "public record R3 (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R3 (int x, int y) implements java.io.Serializable { }"); ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; byteCode = addSerialPersistentFields(byteCode, serialPersistentFields); serializableRecordLoader = new ByteCodeLoader("R3", byteCode, serializableRecordLoader); @@ -115,8 +111,7 @@ public void setup() { { // R4 byte[] byteCode = InMemoryJavaCompiler.compile("R4", "import java.io.Serializable;" + - "public record R4(U u, V v) implements Serializable { }", - "--enable-preview", "-source", VERSION); + "public record R4(U u, V v) implements Serializable { }"); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("v", String.class) }; @@ -132,8 +127,7 @@ public void setup() { " }\n" + " @Override public void readExternal(ObjectInput in) {\n" + " throw new AssertionError(\"should not reach here\");\n" + - " } }", - "--enable-preview", "-source", VERSION); + " } }"); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("v", String.class) }; diff --git a/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java b/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java index 4e76dabd334..d1018c12554 100644 --- a/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java +++ b/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic tests for SUID in the serial stream - * @compile --enable-preview -source ${jdk.version} SerialVersionUIDTest.java - * @run testng/othervm --enable-preview SerialVersionUIDTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview SerialVersionUIDTest + * @run testng SerialVersionUIDTest + * @run testng/othervm/java.security.policy=empty_security.policy SerialVersionUIDTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/StreamRefTest.java b/test/jdk/java/io/Serializable/records/StreamRefTest.java index cb5d5f31557..b0c72ec8a96 100644 --- a/test/jdk/java/io/Serializable/records/StreamRefTest.java +++ b/test/jdk/java/io/Serializable/records/StreamRefTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test + * @bug 8246774 * @summary Tests for stream references - * @compile --enable-preview -source ${jdk.version} StreamRefTest.java - * @run testng/othervm --enable-preview StreamRefTest + * @run testng StreamRefTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java b/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java index 63f3436a10b..feb148f5d5c 100644 --- a/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java +++ b/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Tests constructor invocation exceptions are handled appropriately - * @compile --enable-preview -source ${jdk.version} ThrowingConstructorTest.java - * @run testng/othervm --enable-preview ThrowingConstructorTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview ThrowingConstructorTest + * @run testng ThrowingConstructorTest + * @run testng/othervm/java.security.policy=empty_security.policy ThrowingConstructorTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/UnsharedTest.java b/test/jdk/java/io/Serializable/records/UnsharedTest.java index aac81eef3c4..c96010c83ab 100644 --- a/test/jdk/java/io/Serializable/records/UnsharedTest.java +++ b/test/jdk/java/io/Serializable/records/UnsharedTest.java @@ -23,10 +23,9 @@ /* * @test - * @bug 8238763 + * @bug 8238763 8246774 * @summary ObjectInputStream readUnshared method handling of Records - * @compile --enable-preview -source ${jdk.version} UnsharedTest.java - * @run testng/othervm --enable-preview UnsharedTest + * @run testng UnsharedTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/WriteReplaceTest.java b/test/jdk/java/io/Serializable/records/WriteReplaceTest.java index 228157bf8a9..8dda381e671 100644 --- a/test/jdk/java/io/Serializable/records/WriteReplaceTest.java +++ b/test/jdk/java/io/Serializable/records/WriteReplaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic tests for writeReplace - * @compile --enable-preview -source ${jdk.version} WriteReplaceTest.java - * @run testng/othervm --enable-preview WriteReplaceTest - * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview WriteReplaceTest + * @run testng WriteReplaceTest + * @run testng/othervm/java.security.policy=empty_security.policy WriteReplaceTest */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/io/Serializable/records/migration/AbstractTest.java b/test/jdk/java/io/Serializable/records/migration/AbstractTest.java index 4b0c4547cc8..e0bbc574500 100644 --- a/test/jdk/java/io/Serializable/records/migration/AbstractTest.java +++ b/test/jdk/java/io/Serializable/records/migration/AbstractTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,8 +44,6 @@ */ public class AbstractTest { - private static final String VERSION = Integer.toString(Runtime.version().feature()); - static final String TEST_SRC = System.getProperty("test.src", "."); static final String TEST_CLASSES = System.getProperty("test.classes", "."); static final Path TEST_CLASSES_DIR = Path.of(TEST_CLASSES); @@ -59,11 +57,9 @@ public class AbstractTest { @BeforeTest public void setup() throws IOException { assertTrue(CompilerUtils.compile(PLAIN_SRC_DIR, PLAIN_DEST_DIR, - "--enable-preview", "-source", VERSION, "--class-path", TEST_CLASSES_DIR.toString())); assertTrue(CompilerUtils.compile(RECORD_SRC_DIR, RECORD_DEST_DIR, - "--enable-preview", "-source", VERSION, "--class-path", TEST_CLASSES_DIR.toString())); } diff --git a/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java b/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java index 7c7d6b146a8..6097e2477df 100644 --- a/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java +++ b/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,13 @@ /* * @test + * @bug 8246774 * @summary Test for subtype stream field value assign-ability * @library /test/lib * @modules jdk.compiler - * @compile --enable-preview -source ${jdk.version} AssignableFrom.java Point.java - * DefaultValues.java SuperStreamFields.java AssignableFromTest.java - * @run testng/othervm --enable-preview AssignableFromTest + * @compile AssignableFrom.java Point.java + * DefaultValues.java SuperStreamFields.java + * @run testng AssignableFromTest */ import java.math.BigDecimal; diff --git a/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java b/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java index e7bc63ef559..4af684156c6 100644 --- a/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java +++ b/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,12 @@ /* * @test + * @bug 8246774 * @summary Checks that the appropriate default value is given to the canonical ctr * @library /test/lib * @modules jdk.compiler - * @compile --enable-preview -source ${jdk.version} AssignableFrom.java Point.java - * DefaultValues.java SuperStreamFields.java DefaultValuesTest.java - * @run testng/othervm --enable-preview DefaultValuesTest + * @compile AssignableFrom.java Point.java DefaultValues.java SuperStreamFields.java + * @run testng DefaultValuesTest */ import java.io.ByteArrayOutputStream; diff --git a/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java b/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java index 8788dcc939b..6090d71003e 100644 --- a/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,12 @@ /* * @test + * @bug 8246774 * @summary superclass fields in the stream should be discarded * @library /test/lib * @modules jdk.compiler - * @compile --enable-preview -source ${jdk.version} AssignableFrom.java Point.java - * DefaultValues.java SuperStreamFields.java SuperStreamFieldsTest.java - * @run testng/othervm --enable-preview SuperStreamFieldsTest + * @compile AssignableFrom.java Point.java DefaultValues.java SuperStreamFields.java + * @run testng SuperStreamFieldsTest */ import org.testng.annotations.DataProvider; diff --git a/test/jdk/java/lang/instrument/RedefineRecordAttr/TestRecordAttr.java b/test/jdk/java/lang/instrument/RedefineRecordAttr/TestRecordAttr.java index 349cf1c7534..fddac8812d9 100644 --- a/test/jdk/java/lang/instrument/RedefineRecordAttr/TestRecordAttr.java +++ b/test/jdk/java/lang/instrument/RedefineRecordAttr/TestRecordAttr.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8246774 * @summary Class redefinition must preclude changes to Record attributes * @comment This is a copy of test/jdk/java/lang/instrument/RedefineNestmateAttr/ * @comment modified for records and the Record attribute. @@ -33,15 +34,14 @@ * java.instrument * @compile ../NamedBuffer.java * @run main RedefineClassHelper - * @compile --enable-preview -source ${jdk.version} Host/Host.java - * @compile --enable-preview -source ${jdk.version} TestRecordAttr.java - * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+record=trace TestRecordAttr Host - * @compile --enable-preview -source ${jdk.version} HostA/Host.java - * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+record=trace TestRecordAttr HostA - * @compile --enable-preview -source ${jdk.version} HostAB/Host.java - * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+record=trace TestRecordAttr HostAB - * @compile --enable-preview -source ${jdk.version} HostABC/Host.java - * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+record=trace TestRecordAttr HostABC + * @compile Host/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttr Host + * @compile HostA/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttr HostA + * @compile HostAB/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttr HostAB + * @compile HostABC/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttr HostABC */ /* Test Description @@ -269,8 +269,6 @@ static void compile(String dir) throws Throwable { " to: " + dst); CompilerUtils.compile(src.toPath(), dst.toPath(), - false /* don't recurse */, - "--enable-preview", - "--source", VERSION); + false /* don't recurse */); } } diff --git a/test/jdk/java/lang/instrument/RedefineRecordAttrGenericSig/TestRecordAttrGenericSig.java b/test/jdk/java/lang/instrument/RedefineRecordAttrGenericSig/TestRecordAttrGenericSig.java index 05362176fdd..af5a6dc4bd2 100644 --- a/test/jdk/java/lang/instrument/RedefineRecordAttrGenericSig/TestRecordAttrGenericSig.java +++ b/test/jdk/java/lang/instrument/RedefineRecordAttrGenericSig/TestRecordAttrGenericSig.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8246774 * @summary Class redefinition must preclude changes to Record attributes * @comment This is a copy of test/jdk/java/lang/instrument/RedefineNestmateAttr/ * @comment modified for records and the Record attribute. @@ -33,11 +34,10 @@ * java.instrument * @compile ../NamedBuffer.java * @run main RedefineClassHelper - * @compile --enable-preview --source ${jdk.version} Host/Host.java - * @compile --enable-preview --source ${jdk.version} TestRecordAttrGenericSig.java - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace --enable-preview TestRecordAttrGenericSig Host - * @compile --enable-preview --source ${jdk.version} HostA/Host.java - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace --enable-preview TestRecordAttrGenericSig HostA + * @compile Host/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttrGenericSig Host + * @compile HostA/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+record=trace TestRecordAttrGenericSig HostA */ /* Test Description @@ -207,8 +207,6 @@ static void compile(String dir) throws Throwable { " to: " + dst); CompilerUtils.compile(src.toPath(), dst.toPath(), - false /* don't recurse */, - "--enable-preview", - "--source", VERSION); + false /* don't recurse */); } } diff --git a/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java b/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java index 085ff908f60..ff25a14c29a 100644 --- a/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java +++ b/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java @@ -44,7 +44,7 @@ import static org.junit.Assert.*; -public class MethodHandlesPermuteArgumentsTest extends MethodHandlesTest { +public class MethodHandlesPermuteArgumentsTest extends test.java.lang.invoke.MethodHandlesTest { @Test // SLOW public void testPermuteArguments() throws Throwable { @@ -58,6 +58,11 @@ public void testPermuteArguments0() throws Throwable { if (CAN_TEST_LIGHTLY) return; testPermuteArguments(4, Integer.class, 2, String.class, 0); testPermuteArguments(6, Integer.class, 0, null, 30); + + testBadReorderArrayLength(); + testBadReorderIndex(); + testReturnTypeMismatch(); + testReorderTypeMismatch(); } public void testPermuteArguments(int max, Class type1, int t2c, Class type2, int dilution) throws Throwable { @@ -191,4 +196,57 @@ void testPermuteArguments(Object[] args, Class[] types, int[] reorder) throws } assertEquals(expected, result); } + + public void testBadReorderArrayLength() throws Throwable { + MethodHandle mh = MethodHandles.empty(MethodType.methodType(void.class, int.class, int.class, String.class)); + MethodType newType = MethodType.methodType(void.class, int.class, String.class); + assertThrows(() -> MethodHandles.permuteArguments(mh, newType, 0, 1), + IllegalArgumentException.class, ".*old type parameter count and reorder array length do not match.*"); + } + + public void testBadReorderIndex() throws Throwable { + MethodHandle mh = MethodHandles.empty(MethodType.methodType(void.class, int.class, int.class, String.class)); + MethodType newType = MethodType.methodType(void.class, int.class, String.class); + assertThrows(() -> MethodHandles.permuteArguments(mh, newType, 0, 0, 2), + IllegalArgumentException.class, ".*index is out of bounds for new type.*"); + assertThrows(() -> MethodHandles.permuteArguments(mh, newType, 0, 0, -1), + IllegalArgumentException.class, ".*index is out of bounds for new type.*"); + } + + public void testReturnTypeMismatch() throws Throwable { + MethodHandle mh = MethodHandles.empty(MethodType.methodType(void.class, int.class, int.class, String.class)); + MethodType newType = MethodType.methodType(int.class, int.class, String.class); + assertThrows(() -> MethodHandles.permuteArguments(mh, newType, 0, 0, 1), + IllegalArgumentException.class, ".*return types do not match.*"); + } + + public void testReorderTypeMismatch() throws Throwable { + MethodHandle mh = MethodHandles.empty(MethodType.methodType(void.class, int.class, int.class, String.class)); + MethodType newType = MethodType.methodType(void.class, double.class, String.class); + assertThrows(() -> MethodHandles.permuteArguments(mh, newType, 0, 0, 1), + IllegalArgumentException.class, ".*parameter types do not match after reorder.*"); + } + + private interface RunnableX { + void run() throws Throwable; + } + + private static void assertThrows(RunnableX r, Class exceptionClass, String messagePattern) throws Throwable { + try { + r.run(); + fail("Exception expected"); + } catch (Throwable e) { + if (exceptionClass.isInstance(e)) { + assertMatches(e.getMessage(), messagePattern); + } else { + throw e; + } + } + } + + private static void assertMatches(String str, String pattern) { + if (!str.matches(pattern)) { + throw new AssertionError("'" + str + "' did not match the pattern '" + pattern + "'."); + } + } } diff --git a/test/jdk/java/lang/invoke/lambda/superProtectedMethod/SuperMethodTest.java b/test/jdk/java/lang/invoke/lambda/superProtectedMethod/SuperMethodTest.java index 333e87669db..624d2173a35 100644 --- a/test/jdk/java/lang/invoke/lambda/superProtectedMethod/SuperMethodTest.java +++ b/test/jdk/java/lang/invoke/lambda/superProtectedMethod/SuperMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,11 @@ /* * @test - * @bug 8227415 - * @run main p.SuperMethodTest + * @bug 8227415 8254975 + * @run testng/othervm p.SuperMethodTest * @summary method reference to a protected method inherited from its - * superclass in a different package must be accessed via - * a bridge method. Lambda proxy class has no access to it. + * superclass in a different runtime package where + * lambda proxy class has no access to it. */ package p; @@ -35,12 +35,24 @@ import q.I; import q.J; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Function; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + public class SuperMethodTest { - public static void main(String... args) { + @Test + public static void remotePackageSameLoader() { Sub_I sub = new Sub_I(); sub.test(Paths.get("test")); } @@ -62,4 +74,68 @@ public void test(Path path) { c.check(path); } } + + @Test + public static void splitPackage() throws Throwable { + ClassLoader parent = new Loader("loader-A", null, A.class); + ClassLoader loader = new Loader("loader-B", parent, B.class); + Class aClass = Class.forName(A.class.getName(), false, loader); + Class bClass = Class.forName(B.class.getName(), false, loader); + assertTrue(aClass.getClassLoader() == parent); + assertTrue(bClass.getClassLoader() == loader); + assertEquals(aClass.getPackageName(), bClass.getPackageName()); + + Object b = bClass.getDeclaredConstructor().newInstance(); + + // verify subclass can access a protected member inherited from + // its superclass in a split package + MethodHandle test = MethodHandles.lookup() + .findVirtual(bClass, "test", MethodType.methodType(void.class)); + test.invoke(b); + + // verify lambda can access a protected member inherited from + // a superclass of the host class where the superclass is in + // a split package (not the same runtime package as the host class) + MethodHandle get = MethodHandles.lookup() + .findVirtual(bClass, "get", MethodType.methodType(Runnable.class)); + ((Runnable) get.invoke(b)).run(); + } + + static class Loader extends URLClassLoader { + static final Path CLASSES_DIR = Paths.get(System.getProperty("test.class.path")); + private final Class c; + Loader(String name, ClassLoader parent, Class c) { + super(name, new URL[]{}, parent); + this.c = c; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals(c.getName())) { + try { + String path = name.replace('.', '/') + ".class"; + byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(path)); + return defineClass(name, bytes, 0, bytes.length); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + return super.findClass(name); + } + + } + + public static class A { + protected void func() { } + } + + public static class B extends A { + public Runnable get() { + return this::func; + } + public void test() { + func(); + } + } } diff --git a/test/jdk/java/lang/runtime/ObjectMethodsTest.java b/test/jdk/java/lang/runtime/ObjectMethodsTest.java index f7b008b2400..373e718b45c 100644 --- a/test/jdk/java/lang/runtime/ObjectMethodsTest.java +++ b/test/jdk/java/lang/runtime/ObjectMethodsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ /* * @test + * @bug 8246774 * @summary Basic tests for ObjectMethods - * @compile --enable-preview -source ${jdk.version} ObjectMethodsTest.java - * @run testng/othervm --enable-preview ObjectMethodsTest - * @run testng/othervm/java.security.policy=empty.policy --enable-preview ObjectMethodsTest + * @run testng ObjectMethodsTest + * @run testng/othervm/java.security.policy=empty.policy ObjectMethodsTest */ import java.lang.invoke.CallSite; diff --git a/test/jdk/java/net/UnixDomainSocketAddress/AddressTest.java b/test/jdk/java/net/UnixDomainSocketAddress/AddressTest.java new file mode 100644 index 00000000000..80bc3ae1033 --- /dev/null +++ b/test/jdk/java/net/UnixDomainSocketAddress/AddressTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8231358 + * @compile ../../nio/file/spi/TestProvider.java AddressTest.java + * @run testng/othervm AddressTest + */ + +import java.net.UnixDomainSocketAddress; +import java.net.URI; +import java.nio.file.FileSystems; +import java.nio.file.spi.FileSystemProvider; +import java.nio.file.Path; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertThrows; + +/** + * Verify that UnixDomainSocketAddress.of(path) throws IAE + * if given a Path that does not originate from system default + * file system. + */ +public class AddressTest { + + // Expected exception + private static final Class IAE = + IllegalArgumentException.class; + + @Test + public static void runTest() throws Exception { + TestProvider prov = new TestProvider(FileSystems.getDefault().provider()); + Path path = prov.getPath(URI.create("file:/")); + assertThrows(IAE, () -> UnixDomainSocketAddress.of(path)); + } +} diff --git a/test/jdk/java/net/UnixDomainSocketAddress/LengthTest.java b/test/jdk/java/net/UnixDomainSocketAddress/LengthTest.java new file mode 100644 index 00000000000..c34c8e001b7 --- /dev/null +++ b/test/jdk/java/net/UnixDomainSocketAddress/LengthTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test UnixDomainSocketAddress constructor + * @library /test/lib + * @run testng/othervm LengthTest + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.lang.System.out; +import static java.net.StandardProtocolFamily.UNIX; +import static jdk.test.lib.Asserts.assertTrue; + +import java.net.UnixDomainSocketAddress; +import java.io.IOException; +import java.nio.channels.SocketChannel; +import java.nio.file.Path; + +public class LengthTest { + final int namelen = 100; // length close to max + + @DataProvider(name = "strings") + public Object[][] strings() { + if (namelen == -1) + return new Object[][] {new String[]{""}}; + + return new Object[][]{ + {""}, + {new String(new char[100]).replaceAll("\0", "x")}, + {new String(new char[namelen]).replaceAll("\0", "x")}, + {new String(new char[namelen-1]).replaceAll("\0", "x")}, + }; + } + + @Test(dataProvider = "strings") + public void expectPass(String s) { + var addr = UnixDomainSocketAddress.of(s); + assertTrue(addr.getPath().toString().equals(s), "getPathName.equals(s)"); + var p = Path.of(s); + addr = UnixDomainSocketAddress.of(p); + assertTrue(addr.getPath().equals(p), "getPath.equals(p)"); + } + + @Test + public void expectNPE() { + try { + String s = null; + UnixDomainSocketAddress.of(s); + throw new RuntimeException("Expected NPE"); + } catch (NullPointerException npe) { + out.println("\tCaught expected exception: " + npe); + } + try { + Path p = null; + UnixDomainSocketAddress.of(p); + throw new RuntimeException("Expected NPE"); + } catch (NullPointerException npe) { + out.println("\tCaught expected exception: " + npe); + } + } +} diff --git a/test/jdk/java/net/UnixDomainSocketAddress/UnixDomainSocketAddressSerializationTest.java b/test/jdk/java/net/UnixDomainSocketAddress/UnixDomainSocketAddressSerializationTest.java new file mode 100644 index 00000000000..305b4bee95e --- /dev/null +++ b/test/jdk/java/net/UnixDomainSocketAddress/UnixDomainSocketAddressSerializationTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.net.UnixDomainSocketAddress; +import java.nio.file.Path; +import static java.io.ObjectStreamConstants.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.expectThrows; + +/* + * @test + * @summary UnixDomainSocketAddress serialization test + * @run testng/othervm UnixDomainSocketAddressSerializationTest + */ + +@Test +public class UnixDomainSocketAddressSerializationTest { + private static final UnixDomainSocketAddress addr = + UnixDomainSocketAddress.of(Path.of("test.sock")); + + public static void test() throws Exception { + assertTrue(addr instanceof Serializable); + + byte[] serialized = serialize(addr); + assertTrue(serialized.length > 0); + + UnixDomainSocketAddress deserialized = + deserialize(serialized, UnixDomainSocketAddress.class); + assertEquals(deserialized.getPath(), addr.getPath()); + assertEquals(deserialized.toString(), addr.toString()); + assertEquals(deserialized.hashCode(), addr.hashCode()); + assertEquals(deserialized, addr); + } + + static final Class IOE = InvalidObjectException.class; + static final Class NPE = NullPointerException.class; + + /** Tests that UnixDomainSocketAddress in the byte-stream is disallowed. */ + public static void testUnixDomainSocketAddressInStream() throws Exception { + long suid = ObjectStreamClass.lookup(UnixDomainSocketAddress.class).getSerialVersionUID(); + byte[] bytes = byteStreamFor(UnixDomainSocketAddress.class.getName(), suid); + expectThrows(IOE, () -> deserialize(bytes, UnixDomainSocketAddress.class)); + } + + /** Tests that SerialProxy with a null/absent path value in the byte-stream is disallowed. */ + public static void testSerialProxyNoStreamValues() throws Exception { + Class c = Class.forName("java.net.UnixDomainSocketAddress$Ser"); + long suid = ObjectStreamClass.lookup(c).getSerialVersionUID(); + byte[] bytes = byteStreamFor(c.getName(), suid); + expectThrows(NPE, () -> deserialize(bytes, UnixDomainSocketAddress.class)); + } + + private static byte[] serialize(T t) + throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(t); + oos.flush(); + oos.close(); + return bos.toByteArray(); + } + + private static T deserialize(byte[] b, Class cl) + throws IOException, ClassNotFoundException { + try (ObjectInputStream ois = + new ObjectInputStream(new ByteArrayInputStream(b))) { + Object o = ois.readObject(); + return cl.cast(o); + } + } + + /** + * Returns a stream with the given classname and suid. The stream will have + * no stream field values. + */ + static byte[] byteStreamFor(String classname, long suid) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + dos.writeShort(STREAM_MAGIC); + dos.writeShort(STREAM_VERSION); + dos.writeByte(TC_OBJECT); + dos.writeByte(TC_CLASSDESC); + dos.writeUTF(classname); + dos.writeLong(suid); + dos.writeByte(SC_SERIALIZABLE); + dos.writeShort(0); // number of stream fields + dos.writeByte(TC_ENDBLOCKDATA); // no annotations + dos.writeByte(TC_NULL); // no superclasses + dos.write(TC_ENDBLOCKDATA); // end block - for SC_WRITE_METHOD + dos.close(); + return baos.toByteArray(); + } +} diff --git a/test/jdk/java/nio/channels/DatagramChannel/Connect.java b/test/jdk/java/nio/channels/DatagramChannel/Connect.java index c2d837289b4..a02b5fcf105 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/Connect.java +++ b/test/jdk/java/nio/channels/DatagramChannel/Connect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ /* @test * @bug 4313882 7183800 * @summary Test DatagramChannel's send and receive methods - * @author Mike McCloskey */ import java.io.*; @@ -32,7 +31,11 @@ import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; - +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.stream.Stream; public class Connect { @@ -43,124 +46,127 @@ public static void main(String[] args) throws Exception { } static void test() throws Exception { - Reactor r = new Reactor(); - Actor a = new Actor(r.port()); - invoke(a, r); + ExecutorService threadPool = Executors.newCachedThreadPool(); + try (Reactor r = new Reactor(); + Actor a = new Actor(r.getSocketAddress()) + ) { + invoke(threadPool, a, r); + } finally { + threadPool.shutdown(); + } } - static void invoke(Sprintable reader, Sprintable writer) throws Exception { - - Thread writerThread = new Thread(writer); - writerThread.start(); - - Thread readerThread = new Thread(reader); - readerThread.start(); - - writerThread.join(); - readerThread.join(); - - reader.throwException(); - writer.throwException(); + static void invoke(ExecutorService e, Runnable reader, Runnable writer) throws CompletionException { + CompletableFuture f1 = CompletableFuture.runAsync(writer, e); + CompletableFuture f2 = CompletableFuture.runAsync(reader, e); + wait(f1, f2); } - public interface Sprintable extends Runnable { - public void throwException() throws Exception; - } - public static class Actor implements Sprintable { - final int port; - Exception e = null; + // This method waits for either one of the given futures to complete exceptionally + // or for all of the given futures to complete successfully. + private static void wait(CompletableFuture... futures) throws CompletionException { + CompletableFuture future = CompletableFuture.allOf(futures); + Stream.of(futures) + .forEach(f -> f.exceptionally(ex -> { + future.completeExceptionally(ex); + return null; + })); + future.join(); + } - Actor(int port) { - this.port = port; - } + public static class Actor implements AutoCloseable, Runnable { + final SocketAddress socketAddress; + final DatagramChannel dc; - public void throwException() throws Exception { - if (e != null) - throw e; + Actor(SocketAddress socketAddress) throws IOException { + this.socketAddress = socketAddress; + dc = DatagramChannel.open(); } public void run() { try { - DatagramChannel dc = DatagramChannel.open(); - - // Send a message ByteBuffer bb = ByteBuffer.allocateDirect(256); bb.put("hello".getBytes()); bb.flip(); - InetAddress address = InetAddress.getLocalHost(); - if (address.isLoopbackAddress()) { - address = InetAddress.getLoopbackAddress(); - } - InetSocketAddress isa = new InetSocketAddress(address, port); - dc.connect(isa); + dc.connect(socketAddress); + + // Send a message + log.println("Actor attempting to write to Reactor at " + socketAddress.toString()); dc.write(bb); // Try to send to some other address - address = InetAddress.getLocalHost(); - InetSocketAddress bogus = new InetSocketAddress(address, 3333); try { - dc.send(bb, bogus); - throw new RuntimeException("Allowed bogus send while connected"); + int port = dc.socket().getLocalPort(); + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress otherAddress = new InetSocketAddress(loopback, (port == 3333 ? 3332 : 3333)); + log.println("Testing if Actor throws AlreadyConnectedException" + otherAddress.toString()); + dc.send(bb, otherAddress); + throw new RuntimeException("Actor allowed send to other address while already connected"); } catch (AlreadyConnectedException ace) { // Correct behavior } // Read a reply bb.flip(); + log.println("Actor waiting to read"); dc.read(bb); bb.flip(); - CharBuffer cb = Charset.forName("US-ASCII"). - newDecoder().decode(bb); - log.println("From Reactor: "+isa+ " said " +cb); - - // Clean up - dc.disconnect(); - dc.close(); + CharBuffer cb = StandardCharsets.US_ASCII. + newDecoder().decode(bb); + log.println("Actor received from Reactor at " + socketAddress + ": " + cb); } catch (Exception ex) { - e = ex; + log.println("Actor threw exception: " + ex); + throw new RuntimeException(ex); + } finally { + log.println("Actor finished"); } } + + @Override + public void close() throws IOException { + dc.close(); + } } - public static class Reactor implements Sprintable { + public static class Reactor implements AutoCloseable, Runnable { final DatagramChannel dc; - Exception e = null; Reactor() throws IOException { - dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + dc = DatagramChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); } - int port() { - return dc.socket().getLocalPort(); - } - - public void throwException() throws Exception { - if (e != null) - throw e; + SocketAddress getSocketAddress() throws IOException { + return dc.getLocalAddress(); } public void run() { try { // Listen for a message ByteBuffer bb = ByteBuffer.allocateDirect(100); + log.println("Reactor waiting to receive"); SocketAddress sa = dc.receive(bb); bb.flip(); - CharBuffer cb = Charset.forName("US-ASCII"). - newDecoder().decode(bb); - log.println("From Actor: "+sa+ " said " +cb); + CharBuffer cb = StandardCharsets.US_ASCII. + newDecoder().decode(bb); + log.println("Reactor received from Actor at" + sa + ": " + cb); // Reply to sender dc.connect(sa); bb.flip(); + log.println("Reactor attempting to write: " + dc.getRemoteAddress().toString()); dc.write(bb); - - // Clean up - dc.disconnect(); - dc.close(); } catch (Exception ex) { - e = ex; + log.println("Reactor threw exception: " + ex); + throw new RuntimeException(ex); + } finally { + log.println("Reactor finished"); } } + + @Override + public void close() throws IOException { + dc.close(); + } } } diff --git a/test/jdk/java/nio/channels/etc/ProtocolFamilies.java b/test/jdk/java/nio/channels/etc/ProtocolFamilies.java index 0df09571a5d..45226e9a97e 100644 --- a/test/jdk/java/nio/channels/etc/ProtocolFamilies.java +++ b/test/jdk/java/nio/channels/etc/ProtocolFamilies.java @@ -35,6 +35,7 @@ import static java.net.StandardProtocolFamily.INET; import static java.net.StandardProtocolFamily.INET6; import static jdk.test.lib.net.IPSupport.*; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertThrows; /* @@ -305,26 +306,30 @@ public void testUoe() { private static SocketChannel openSC(StandardProtocolFamily family) throws IOException { - return family == null ? SocketChannel.open() + SocketChannel sc = family == null ? SocketChannel.open() : SocketChannel.open(family); + return sc; } private static ServerSocketChannel openSSC(StandardProtocolFamily family) throws IOException { - return family == null ? ServerSocketChannel.open() + ServerSocketChannel ssc = family == null ? ServerSocketChannel.open() : ServerSocketChannel.open(family); + return ssc; } private static DatagramChannel openDC(StandardProtocolFamily family) throws IOException { - return family == null ? DatagramChannel.open() + DatagramChannel dc = family == null ? DatagramChannel.open() : DatagramChannel.open(family); + return dc; } private static SocketAddress getSocketAddress(StandardProtocolFamily family) { return family == null ? null : switch (family) { case INET -> new InetSocketAddress(ia4, 0); case INET6 -> new InetSocketAddress(ia6, 0); + default -> throw new RuntimeException("Unexpected protocol family"); }; } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CloseTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CloseTest.java index e42c8ba7ad2..6ea1f34e831 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CloseTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CloseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * * The test launches the "echo service" with arguments to instruct the * service to close the channel after it receives a small message. The - * service then delays/lingers for 15 seconds before shuting down. To + * service then delays/lingers for 15 seconds before shutting down. To * prove that the close works we check that we see EOF (meaning the * peer has closed the connection) in less than 15 seconds. */ @@ -54,8 +54,7 @@ public static void main(String args[]) throws Exception { service_args[0] = String.valueOf(msg.length()); service_args[1] = String.valueOf( Utils.adjustTimeout(15*1000) ); - - SocketChannel sc = Launcher.launchWithSocketChannel("EchoService", service_args); + SocketChannel sc = Launcher.launchWithInetSocketChannel("EchoService", null, service_args); // send message - service will echo the message and close the connection. diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java index 6ec6cb730c1..9931f42c458 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ public class EchoTest { * that it matches the original message. */ private static void TCPEchoTest() throws IOException { - SocketChannel sc = Launcher.launchWithSocketChannel(ECHO_SERVICE, null); + SocketChannel sc = Launcher.launchWithInetSocketChannel(ECHO_SERVICE, null); String msg = "Where's that damn torpedo?"; int repeat = 100; diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java index 389c41c842c..2db3480d4d6 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java @@ -85,6 +85,7 @@ public Object[][] testCases() { // These system properties are passed to the launched service as options: // java [-options] class [args...] + { "StateTest run with " + POLICY_PASS, List.of(StateTest.class.getName(), "-Djava.security.manager", "-Djava.security.policy=" diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java index fea44e1f685..8e166582819 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +28,15 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; import java.nio.channels.DatagramChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; +import java.nio.file.Files; + +import static java.net.StandardProtocolFamily.UNIX; public class Launcher { @@ -63,81 +68,101 @@ private static void launch(String className, String options[], String args[], in launch0(cmdarray, fd); } - /** - * Launch 'java' with specified class using a UnixDomainSocket pair linking calling - * process to the child VM. UnixDomainSocket is a simplified interface to PF_UNIX sockets - * which supports byte a time reads and writes. + * Launch 'java' with specified class. The launched process will inherit + * a connected Unix Domain socket. The remote endpoint will be the + * SocketChannel returned by this method. */ - public static UnixDomainSocket launchWithUnixDomainSocket(String className) throws IOException { - UnixDomainSocket[] socks = UnixDomainSocket.socketpair(); - launch(className, null, null, socks[0].fd()); - socks[0].close(); - return socks[1]; + public static SocketChannel launchWithUnixSocketChannel(String className) + throws IOException + { + UnixDomainSocketAddress addr = null; + try (ServerSocketChannel ssc = ServerSocketChannel.open(UNIX)) { + addr = (UnixDomainSocketAddress)ssc.bind(null).getLocalAddress(); + SocketChannel sc1 = SocketChannel.open(addr); + try (SocketChannel sc2 = ssc.accept()) { + launch(className, null, null, Util.getFD(sc2)); + } + return sc1; + } finally { + if (addr != null) + Files.delete(addr.getPath()); + } } /** - * Launch specified class with an AF_UNIX socket created externally, and one String arg to child VM - */ - public static void launchWithUnixDomainSocket(String className, UnixDomainSocket socket, String arg) throws IOException { - String[] args = new String[1]; - args[0] = arg; - launch(className, null, args, socket.fd()); - } - - /* * Launch 'java' with specified class with the specified arguments (may be null). * The launched process will inherit a connected TCP socket. The remote endpoint * will be the SocketChannel returned by this method. */ - public static SocketChannel launchWithSocketChannel(String className, String options[], String args[]) throws IOException { - ServerSocketChannel ssc = ServerSocketChannel.open(); - ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); - InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), + public static SocketChannel launchWithInetSocketChannel(String className, + String options[], + String... args) + throws IOException + { + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { + ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); + InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort()); - SocketChannel sc1 = SocketChannel.open(isa); - SocketChannel sc2 = ssc.accept(); - launch(className, options, args, Util.getFD(sc2)); - sc2.close(); - ssc.close(); - return sc1; - } - - public static SocketChannel launchWithSocketChannel(String className, String args[]) throws IOException { - return launchWithSocketChannel(className, null, args); + SocketChannel sc1 = SocketChannel.open(isa); + try (SocketChannel sc2 = ssc.accept()) { + launch(className, options, args, Util.getFD(sc2)); + } + return sc1; + } } - public static SocketChannel launchWithSocketChannel(String className) throws IOException { - return launchWithSocketChannel(className, null); + /** + * Launch specified class with a SocketChannel created externally. + */ + public static void launchWithSocketChannel(String className, + SocketChannel sc, + String[] options, + String... args) throws Exception { + launch(className, options, args, Util.getFD(sc)); } - /* + /** * Launch 'java' with specified class with the specified arguments (may be null). * The launched process will inherited a TCP listener socket. * Once launched this method tries to connect to service. If a connection * can be established a SocketChannel, connected to the service, is returned. */ - public static SocketChannel launchWithServerSocketChannel(String className, String options[], String args[]) - throws IOException + public static SocketChannel launchWithInetServerSocketChannel(String className, + String[] options, + String... args) + throws IOException { - ServerSocketChannel ssc = ServerSocketChannel.open(); - ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); - int port = ssc.socket().getLocalPort(); - launch(className, options, args, Util.getFD(ssc)); - ssc.close(); - InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), port); - return SocketChannel.open(isa); + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { + ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); + int port = ssc.socket().getLocalPort(); + launch(className, options, args, Util.getFD(ssc)); + InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), port); + return SocketChannel.open(isa); + } } - public static SocketChannel launchWithServerSocketChannel(String className, String args[]) throws IOException { - return launchWithServerSocketChannel(className, null, args); + public static SocketChannel launchWithUnixServerSocketChannel(String className) throws IOException { + ServerSocketChannel ssc = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + ssc.bind(null); + var addr = ssc.getLocalAddress(); + launch(className, null, null, Util.getFD(ssc)); + ssc.close(); + return SocketChannel.open(addr); } - public static SocketChannel launchWithServerSocketChannel(String className) throws IOException { - return launchWithServerSocketChannel(className, null); + /** + * Launch specified class with a ServerSocketChannel created externally. + */ + public static void launchWithServerSocketChannel(String className, + ServerSocketChannel ssc, + String[] options, + String... args) + throws Exception { + launch(className, options, args, Util.getFD(ssc)); } - /* + /** * Launch 'java' with specified class with the specified arguments (may be null). * The launch process will inherited a bound UDP socket. * Once launched this method creates a DatagramChannel and "connects @@ -145,9 +170,10 @@ public static SocketChannel launchWithServerSocketChannel(String className) thro * As it is connected any packets sent from the socket will be * sent to the service. */ - public static DatagramChannel launchWithDatagramChannel(String className, String options[], String args[]) - throws IOException - { + public static DatagramChannel launchWithDatagramChannel(String className, + String[] options, + String... args) + throws IOException { InetAddress address = InetAddress.getLocalHost(); if (address.isLoopbackAddress()) { address = InetAddress.getLoopbackAddress(); @@ -165,12 +191,4 @@ public static DatagramChannel launchWithDatagramChannel(String className, String dc.connect(isa); return dc; } - - public static DatagramChannel launchWithDatagramChannel(String className, String args[]) throws IOException { - return launchWithDatagramChannel(className, null, args); - } - - public static DatagramChannel launchWithDatagramChannel(String className) throws IOException { - return launchWithDatagramChannel(className, null); - } } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java index c8d048eb4e4..8b70defc021 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,8 +170,8 @@ public static void main(String args[]) throws IOException { /* * Launch service with a SocketChannel (tcp nowait) */ - System.err.println("launchWithSocketChannel"); - SocketChannel sc = Launcher.launchWithSocketChannel(TEST_SERVICE, options, arg); + System.err.println("launchWithInetSocketChannel"); + SocketChannel sc = Launcher.launchWithInetSocketChannel(TEST_SERVICE, options, arg); System.err.println("Waiting for test results"); waitForTestResult(ssc, expectFail); sc.close(); @@ -181,8 +181,8 @@ public static void main(String args[]) throws IOException { * launchWithServerSocketChannel establishes a connection to the service * and the returned SocketChannel is connected to the service. */ - System.err.println("launchWithServerSocketChannel"); - sc = Launcher.launchWithServerSocketChannel(TEST_SERVICE, options, arg); + System.err.println("launchWithInetServerSocketChannel"); + sc = Launcher.launchWithInetServerSocketChannel(TEST_SERVICE, options, arg); waitForTestResult(ssc, expectFail); sc.close(); diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTestService.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTestService.java index cfc481b46a2..eac73528709 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTestService.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTestService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * A test service for use in the inetd/System.inheritedChannel unit * tests. * - * The test checks that the channel returned by System.inheritiedChannel + * The test checks that the channel returned by System.inheritedChannel * is in blocking mode and is bound. In addition, in the case of a * SocketChannel checks that the socket is connected. * diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java index 698d6c5f3d5..fbe5b0ef142 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,41 +21,50 @@ * questions. */ +import java.io.IOException; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.channels.*; import java.nio.ByteBuffer; -import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static java.net.StandardProtocolFamily.UNIX; import static java.nio.charset.StandardCharsets.ISO_8859_1; /* - * Make sure that System.inheritedChannel returns null when given a UNIX domain socket + * Make sure that System.inheritedChannel returns the correct type */ public class UnixDomainChannelTest { + private static final UnixDomainSocketAddress SOCK_ADDR = + UnixDomainSocketAddress.of(Path.of("foo.socket")); + + private static boolean passed = true; public static class Child { public static void main(String[] args) throws Exception { - // we just want to make sure that System.inheritedChannel either - // returns a connected channel, or null if it is given a listener + // we want to make sure that System.inheritedChannel either + // returns a ServerSocketChannel or a SocketChannel Channel channel = System.inheritedChannel(); String result = channel == null ? "N" : "Y"; if (args[0].equals("test1") || args[0].equals("test2")) { - // socket is writeable - ByteChannel bc = (ByteChannel)channel; - ByteBuffer buf = ByteBuffer.wrap(result.getBytes(ISO_8859_1)); - bc.write(buf); + if (channel instanceof SocketChannel) { + SocketChannel sc = (SocketChannel) channel; + ByteBuffer buf = ByteBuffer.wrap(result.getBytes(ISO_8859_1)); + sc.write(buf); + } } else { // test3 - // in this case the socket is a listener - // we can't write to it. So, use UnixDatagramSocket - // to accept a writeable socket - UnixDomainSocket listener = new UnixDomainSocket(0); // fd 0 - UnixDomainSocket sock = listener.accept(); - sock.write((int)result.charAt(0)); + if (channel instanceof ServerSocketChannel) { + ServerSocketChannel server = (ServerSocketChannel) channel; + SocketChannel sc = server.accept(); + ByteBuffer buf = ByteBuffer.wrap(result.getBytes(ISO_8859_1)); + sc.write(buf); + } } } } - static boolean passed = true; - public static void main(String args[]) throws Exception { test1(); test2(); @@ -64,54 +73,92 @@ public static void main(String args[]) throws Exception { throw new RuntimeException(); } - private static void closeAll(UnixDomainSocket... sockets) { - for (UnixDomainSocket sock : sockets) { - sock.close(); - } - } - // Test with a named connected socket private static void test1() throws Exception { - UnixDomainSocket listener = new UnixDomainSocket(); - listener.bind("foo.socket"); - UnixDomainSocket sock1 = new UnixDomainSocket(); - sock1.connect("foo.socket"); - UnixDomainSocket sock2 = listener.accept(); - - Launcher.launchWithUnixDomainSocket("UnixDomainChannelTest$Child", sock2, "test1"); - int c = sock1.read(); - if (c != 'Y') { - System.err.printf("test1: failed %d d\n", c ); + ServerSocketChannel listener = ServerSocketChannel.open(UNIX); + listener.bind(SOCK_ADDR); + SocketChannel sock1 = SocketChannel.open(SOCK_ADDR); + SocketChannel sock2 = listener.accept(); + System.out.println("test1: launching child"); + Launcher.launchWithSocketChannel( + "UnixDomainChannelTest$Child", sock2, null, "test1"); + ByteBuffer bb = ByteBuffer.allocate(10); + int c = sock1.read(bb); + if (c != 1) { + System.err.printf("test1: failed " + + "- unexpected number of bytes read %d d\n", c); + passed = false; + } + byte b = bb.get(0); + if (b != 'Y') { + System.err.printf("test1: failed " + + "- unexpected byte read %d d\n", b); passed = false; } closeAll(listener, sock1, sock2); + Files.deleteIfExists(SOCK_ADDR.getPath()); } // Test with unnamed socketpair private static void test2() throws Exception { - UnixDomainSocket[] pair = UnixDomainSocket.socketpair(); + ServerSocketChannel listener = ServerSocketChannel.open(UNIX); + SocketAddress addr = listener.bind(null).getLocalAddress(); + SocketChannel sock1 = SocketChannel.open(addr); + SocketChannel sock2 = listener.accept(); System.out.println("test2: launching child"); - Launcher.launchWithUnixDomainSocket("UnixDomainChannelTest$Child", pair[0], "test2"); - if (pair[1].read() != 'Y') { - System.err.println("test2: failed"); + Launcher.launchWithSocketChannel( + "UnixDomainChannelTest$Child", sock2, null, "test2"); + ByteBuffer bb = ByteBuffer.allocate(10); + int c = sock1.read(bb); + if (c != 1) { + System.err.printf("test3: failed " + + "- unexpected number of bytes read %d d\n", c); + passed = false; + } + byte b = bb.get(0); + if (b != 'Y') { + System.err.printf("test3: failed " + + "- unexpected byte read %d d\n", b); passed = false; } - closeAll(pair[0], pair[1]); + closeAll(listener, sock1, sock2); + Files.deleteIfExists(((UnixDomainSocketAddress)addr).getPath()); } // Test with a named listener private static void test3() throws Exception { - UnixDomainSocket listener = new UnixDomainSocket(); - listener.bind("foo.socket"); - UnixDomainSocket sock1 = new UnixDomainSocket(); + ServerSocketChannel listener = ServerSocketChannel.open(UNIX); + listener.bind(SOCK_ADDR); + SocketChannel sock1 = SocketChannel.open(UNIX); System.out.println("test3: launching child"); - Launcher.launchWithUnixDomainSocket("UnixDomainChannelTest$Child", listener, "test3"); - sock1.connect("foo.socket"); - if (sock1.read() != 'N') { - System.err.println("test3: failed"); + Launcher.launchWithServerSocketChannel( + "UnixDomainChannelTest$Child", listener, null, "test3"); + sock1.connect(SOCK_ADDR); + ByteBuffer bb = ByteBuffer.allocate(10); + int c = sock1.read(bb); + if (c != 1) { + System.err.printf("test3: failed " + + "- unexpected number of bytes read %d d\n", c); + passed = false; + } + byte b = bb.get(0); + if (b != 'Y') { + System.err.printf("test3: failed " + + "- unexpected byte read %d d\n", b); passed = false; } closeAll(listener, sock1); + Files.deleteIfExists(SOCK_ADDR.getPath()); } + private static void closeAll(Channel... channels) { + for (Channel c : channels) { + try { + if (c != null) + c.close(); + } catch (IOException e) { + throw new RuntimeException("Could not close channel " + c); + } + } + } } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainSocket.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainSocket.java deleted file mode 100644 index 5ef18fd050c..00000000000 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainSocket.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2018, 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. - */ - -/** - * A simplified Unix domain socket which can read and write bytes at a time - * used for simulating external launchers which use UNIX sockets to talk - * the VM. - */ - -import java.io.IOException; - -public class UnixDomainSocket { - - static { - System.loadLibrary("InheritedChannel"); - init(); - } - - private final int fd; - private volatile String name; - - public UnixDomainSocket() throws IOException { - this.fd = create(); - } - - public void bind(String name) throws IOException { - bind0(fd, name); - this.name = name; - } - - public UnixDomainSocket accept() throws IOException { - int newsock = accept0(fd); - return new UnixDomainSocket(newsock); - } - - public UnixDomainSocket(int fd) { - this.fd = fd; - } - - public void connect(String dest) throws IOException { - connect0(fd, dest); - } - - public int read() throws IOException { - return read0(fd); - } - - public String name() { - return name; - } - - public void write(int w) throws IOException { - write0(fd, w); - } - - public void close() { - close0(fd, name); // close0 will unlink name if non-null - } - - public int fd() { - return fd; - } - - public String toString() { - return "UnixDomainSocket: fd=" + Integer.toString(fd); - } - - private static native int create() throws IOException; - private static native void bind0(int fd, String name) throws IOException; - private static native int accept0(int fd) throws IOException; - private static native int connect0(int fd, String name) throws IOException; - - /* read and write bytes with UNIX domain sockets */ - - private static native int read0(int fd) throws IOException; - private static native void write0(int fd, int w) throws IOException; - private static native void close0(int fd, String name); - private static native void init(); - public static native UnixDomainSocket[] socketpair(); -} - diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java index 7995b5bac79..6f16d8a1dc3 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,56 +21,68 @@ * questions. */ -/* - * If the platform has IPv6 we spawn a child process simulating the - * effect of being launched from node.js. We check that IPv6 is available in the child - * and report back as appropriate. - */ - -import jdk.test.lib.Utils; -import java.io.*; import java.net.InetAddress; import java.net.Inet6Address; import java.net.NetworkInterface; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.channels.ServerSocketChannel; +import java.nio.file.Files; import java.util.Collections; import java.util.Enumeration; +import static java.net.StandardProtocolFamily.UNIX; + public class UnixSocketTest { - static boolean hasIPv6() throws Exception { - Enumeration nets = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface netint : Collections.list(nets)) { - Enumeration inetAddresses = netint.getInetAddresses(); - for (InetAddress inetAddress : Collections.list(inetAddresses)) { - if (inetAddress instanceof Inet6Address) { - return true; - } - } + public static class Child1 { + public static void main(String[] args) throws Exception { + SocketChannel chan = (SocketChannel)System.inheritedChannel(); + ByteBuffer bb = ByteBuffer.allocate(2); + bb.put((byte)'X'); + bb.put((byte)'Y'); + bb.flip(); + chan.write(bb); + chan.close(); } - return false; } - public static class Child { + public static class Child2 { public static void main(String[] args) throws Exception { - System.out.write('X'); - System.out.flush(); - if (hasIPv6()) { - System.out.println("Y"); // GOOD - } else - System.out.println("N"); // BAD + ServerSocketChannel server = (ServerSocketChannel)System.inheritedChannel(); + SocketChannel chan = server.accept(); + UnixDomainSocketAddress sa = (UnixDomainSocketAddress)server.getLocalAddress(); + Files.delete(sa.getPath()); + server.close(); + ByteBuffer bb = ByteBuffer.allocate(2); + bb.put((byte)'X'); + bb.put((byte)'Y'); + bb.flip(); + chan.write(bb); + chan.close(); } } public static void main(String args[]) throws Exception { - - if (!hasIPv6()) { - return; // can only test if IPv6 is present + SocketChannel sc = Launcher.launchWithUnixSocketChannel("UnixSocketTest$Child1"); + ByteBuffer bb = ByteBuffer.allocate(10); + sc.read(bb); + if (bb.get(0) != 'X') { + System.exit(-2); } - UnixDomainSocket sock = Launcher.launchWithUnixDomainSocket("UnixSocketTest$Child"); - if (sock.read() != 'X') { + if (bb.get(1) != 'Y') { + System.exit(-2); + } + sc.close(); + + sc = Launcher.launchWithUnixServerSocketChannel("UnixSocketTest$Child2"); + bb.clear(); + sc.read(bb); + if (bb.get(0) != 'X') { System.exit(-2); } - if (sock.read() != 'Y') { + if (bb.get(1) != 'Y') { System.exit(-2); } } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/libInheritedChannel.c b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/libInheritedChannel.c index 0ba0986b3a3..c6d493a3e92 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/libInheritedChannel.c +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/libInheritedChannel.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -40,9 +39,6 @@ #define CHECK(X) if ((X) == 0) {printf("JNI init error line %d\n", __LINE__); _exit(1);} -static jclass unixSocketClass; -static jmethodID unixSocketCtor; - /* * Throws the exception of the given class name and detail message */ @@ -85,7 +81,6 @@ static char* getString8859_1Chars(JNIEnv *env, jstring jstr) { return result; } - /* * Class: Launcher * Method: launch0 @@ -145,7 +140,7 @@ JNIEXPORT void JNICALL Java_Launcher_launch0 /* * We need to close all file descriptors except for serviceFd. To - * get the list of open file descriptos we read through /proc/self/fd (/dev/fd) + * get the list of open file descriptors we read through /proc/self/fd (/dev/fd) * but to open this requires a file descriptor. We could use a specific * file descriptor and fdopendir but Linux doesn't seem to support * fdopendir. Instead we use opendir and make an assumption on the @@ -184,131 +179,3 @@ JNIEXPORT void JNICALL Java_Launcher_launch0 execvp(cmdv[0], cmdv); _exit(-1); } - -JNIEXPORT void JNICALL Java_UnixDomainSocket_init(JNIEnv *env, jclass cls) { - CHECK(unixSocketClass = (*env)->FindClass(env, "UnixDomainSocket")); - CHECK(unixSocketClass = (*env)->NewGlobalRef(env, unixSocketClass)); - CHECK(unixSocketCtor = (*env)->GetMethodID(env, unixSocketClass, "", "(I)V")); -} - -/* - * Class: UnixDomainSocket - * Method: socketpair - * Signature: ()[LUnixDomainSocket - */ -JNIEXPORT jobjectArray JNICALL Java_UnixDomainSocket_socketpair - (JNIEnv *env, jclass cls) -{ - int fds[2]; - jobject socket; - jobjectArray result = (*env)->NewObjectArray(env, 2, unixSocketClass, 0); - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - perror("socketpair"); - return result; - } - socket = (*env)->NewObject(env, unixSocketClass, unixSocketCtor, fds[0]); - (*env)->SetObjectArrayElement(env, result, 0, socket); - socket = (*env)->NewObject(env, unixSocketClass, unixSocketCtor, fds[1]); - (*env)->SetObjectArrayElement(env, result, 1, socket); - return result; -} - -JNIEXPORT jint JNICALL Java_UnixDomainSocket_create - (JNIEnv *env, jclass cls) -{ - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) { - ThrowException(env, "java/io/IOException", "socket create error"); - } - return sock; -} - -JNIEXPORT void JNICALL Java_UnixDomainSocket_bind0 - (JNIEnv *env, jclass cls, jint sock, jstring name) -{ - struct sockaddr_un addr; - const char *nameUtf = (*env)->GetStringUTFChars(env, name, NULL); - int ret = -1; - int length = sizeof(addr.sun_path); - unlink(nameUtf); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, nameUtf, length); - addr.sun_path[length - 1] = '\0'; - ret = bind(sock, (const struct sockaddr*)&addr, sizeof(addr)); - if (ret == -1) { - ThrowException(env, "java/io/IOException", "socket bind error"); - } - ret = listen(sock, 5); - if (ret == -1) { - ThrowException(env, "java/io/IOException", "socket bind error"); - } - (*env)->ReleaseStringUTFChars(env, name, nameUtf); -} - -JNIEXPORT jint JNICALL Java_UnixDomainSocket_accept0 - (JNIEnv *env, jclass cls, jint sock) -{ - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - int ret = accept(sock, (struct sockaddr *)&addr, &len); - if (ret == -1) - ThrowException(env, "java/io/IOException", "socket accept error"); - return ret; -} - -JNIEXPORT void JNICALL Java_UnixDomainSocket_connect0 - (JNIEnv *env, jclass cls, jint fd, jstring name) -{ - struct sockaddr_un addr; - const char *nameUtf = (*env)->GetStringUTFChars(env, name, NULL); - int ret = -1; - int length = sizeof(addr.sun_path); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, nameUtf, length); - addr.sun_path[length - 1] = '\0'; - ret = connect(fd, (const struct sockaddr*)&addr, sizeof(addr)); - if (ret == -1) { - ThrowException(env, "java/io/IOException", "socket connect error"); - } - (*env)->ReleaseStringUTFChars(env, name, nameUtf); -} - - -JNIEXPORT jint JNICALL Java_UnixDomainSocket_read0 - (JNIEnv *env, jclass cls, jint fd) -{ - int ret; - unsigned char res; - ret = read(fd, &res, 1); - if (ret == 0) - return -1; /* EOF */ - else if (ret < 0) { - ThrowException(env, "java/io/IOException", "read error"); - return -1; - } - return res; -} - -JNIEXPORT void JNICALL Java_UnixDomainSocket_write0 - (JNIEnv *env, jclass cls, jint fd, jint byte) -{ - int ret; - unsigned char w = (unsigned char)byte; - ret = write(fd, &w, 1); - if (ret < 0) { - ThrowException(env, "java/io/IOException", "write error"); - } -} - -JNIEXPORT void JNICALL Java_UnixDomainSocket_close0 - (JNIEnv *env, jclass cls, jint fd, jstring name) -{ - close(fd); - if (name != NULL) { - const char *nameUtf = (*env)->GetStringUTFChars(env, name, NULL); - unlink(nameUtf); - (*env)->ReleaseStringUTFChars(env, name, nameUtf); - } -} diff --git a/test/jdk/java/nio/channels/unixdomain/Bind.java b/test/jdk/java/nio/channels/unixdomain/Bind.java new file mode 100644 index 00000000000..47fc24ae1af --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/Bind.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @library /test/lib + * @run main/othervm Bind + */ + +import java.io.IOException; +import java.net.*; +import java.nio.channels.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import jtreg.SkippedException; + +/** + * Check that all bind variations work + */ +public class Bind { + + static Path spath, cpath; + + static UnixDomainSocketAddress sAddr, cAddr, UNNAMED, nullAddr; + static ServerSocketChannel server; + static SocketChannel client, accept1; + + public static void main(String args[]) throws Exception { + checkSupported(); + spath = Path.of("server.sock"); + cpath = Path.of("client.sock"); + sAddr = UnixDomainSocketAddress.of(spath); + cAddr = UnixDomainSocketAddress.of(cpath); + nullAddr = UnixDomainSocketAddress.of(""); + UNNAMED = nullAddr; + runTests(); + } + + static void checkSupported() { + try { + SocketChannel.open(StandardProtocolFamily.UNIX).close(); + } catch (UnsupportedOperationException e) { + throw new SkippedException("Unix domain channels not supported"); + } catch (Exception e) { + // continue test to see what problem is + } + } + + static interface ThrowingRunnable { + public void run() throws Exception; + } + + static void init() throws IOException { + Files.deleteIfExists(cpath); + Files.deleteIfExists(spath); + client = null; server = null; accept1 = null; + } + + static void checkNormal(ThrowingRunnable r) { + try { + init(); + r.run(); + System.out.println("PASS:"); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + cleanup(); + } + } + + static void checkException(Class expected, ThrowingRunnable r) { + try { + init(); + r.run(); + throw new RuntimeException("Exception expected"); + } catch (Exception e) { + if (!expected.isAssignableFrom(e.getClass())) { + String msg = "Expected: " + expected + " Got: " + e.getClass(); + throw new RuntimeException(msg); + } + System.out.println("PASS: Got " + e); + } finally { + cleanup(); + } + } + + static void cleanup() { + try { + if (server != null) + server.close(); + if (client != null) + client.close(); + if (accept1 != null) + accept1.close(); + } catch (IOException e) {} + } + + static void assertClientAddress(SocketAddress a) { + assertAddress(a, cAddr, "client"); + } + + static void assertServerAddress(SocketAddress a) { + assertAddress(a, sAddr, "server"); + } + + static void assertAddress(SocketAddress a, UnixDomainSocketAddress a1, String s) { + if (!(a instanceof UnixDomainSocketAddress)) { + throw new RuntimeException("wrong address type"); + } + UnixDomainSocketAddress ua = (UnixDomainSocketAddress)a; + if (!a.equals(a1)) + throw new RuntimeException("this is not the " + s + " address"); + } + + static void assertEquals(Object a, Object b) { + if (!a.equals(b)) + throw new RuntimeException("identity check failed"); + } + + public static void runTests() throws IOException { + checkNormal(() -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(cAddr); + }); + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + }); + // Repeat first two to make sure they are repeatable + checkNormal(() -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(cAddr); + }); + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + }); + // address with space should work + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + UnixDomainSocketAddress usa = UnixDomainSocketAddress.of("with space"); // relative to CWD + Files.deleteIfExists(usa.getPath()); + server.bind(usa); + client = SocketChannel.open(usa); + Files.delete(usa.getPath()); + assertAddress(client.getRemoteAddress(), usa, "address"); + }); + // client bind to null: allowed + checkNormal(() -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(null); + SocketAddress a = client.getLocalAddress(); + assertAddress(a, nullAddr, "null address"); + assertEquals(a, UNNAMED); + }); + // client bind to UNNAMED: allowed + checkNormal(() -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(UNNAMED); + SocketAddress a = client.getLocalAddress(); + assertAddress(a, nullAddr, "null address"); + assertEquals(a, UNNAMED); + }); + // server bind to null: should bind to a local address + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(null); + UnixDomainSocketAddress usa = (UnixDomainSocketAddress)server.getLocalAddress(); + if (usa.getPath().toString().isEmpty()) + throw new RuntimeException("expected non zero address length"); + System.out.println("Null server address: " + server.getLocalAddress()); + }); + // server no bind : not allowed + checkException( + NotYetBoundException.class, () -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.accept(); + } + ); + + // client implicit bind and connect + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + client = SocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + client.connect(sAddr); + SocketAddress cAddr = client.getLocalAddress(); + assertAddress(cAddr, nullAddr, "null address"); + assertEquals(cAddr, UNNAMED); + assertServerAddress(server.getLocalAddress()); + }); + // client null bind and connect (check all addresses) + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + client = SocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + client.bind(null); + client.connect(sAddr); + assertAddress(client.getLocalAddress(), UNNAMED, "unnamed address"); + assertServerAddress(server.getLocalAddress()); + }); + // client explicit bind and connect (check all addresses) + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + client = SocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + client.bind(cAddr); + client.connect(sAddr); + accept1 = server.accept(); + assertClientAddress(client.getLocalAddress()); + assertServerAddress(server.getLocalAddress()); + assertAddress(client.getRemoteAddress(), sAddr, "client's remote server address"); + assertAddress(accept1.getLocalAddress(), sAddr, "accepted local address (server)"); + assertAddress(accept1.getRemoteAddress(), cAddr, "accepted remote address (client)"); + }); + // server multiple bind : not allowed + checkException( + AlreadyBoundException.class, () -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(sAddr); + server.bind(sAddr); + } + ); + // client multiple bind : not allowed + checkException( + AlreadyBoundException.class, () -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(cAddr); + client.bind(cAddr); + } + ); + // client multiple bind to different addresses: not allowed + checkException( + AlreadyBoundException.class, () -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(cAddr); + client.bind(sAddr); + } + ); + // client multiple bind to differnt addresses, incl null: not allowed + checkException( + AlreadyBoundException.class, () -> { + client = SocketChannel.open(StandardProtocolFamily.UNIX); + client.bind(null); + client.bind(cAddr); + } + ); + + // server bind to existing name: not allowed + + checkException( + BindException.class, () -> { + var path = Files.createFile(Path.of("moo.sock")); + var addr = UnixDomainSocketAddress.of(path); + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + try { + server.bind(addr); + } finally { + Files.deleteIfExists(path); + } + } + ); + + + // client bind to existing name: not allowed + checkException( + BindException.class, () -> { + var path = Path.of("temp.sock"); + Files.deleteIfExists(path); + Files.createFile(path); + var addr = UnixDomainSocketAddress.of(path); + client = SocketChannel.open(StandardProtocolFamily.UNIX); + try { + client.bind(addr); + } finally { + Files.deleteIfExists(path); + } + } + ); + + // bind and connect to name of close to max size + checkNormal(() -> { + int len = 100; + char[] chars = new char[len]; + Arrays.fill(chars, 'x'); + String name = new String(chars); + UnixDomainSocketAddress address = UnixDomainSocketAddress.of(name); + ServerSocketChannel server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(address); + SocketChannel client = SocketChannel.open(address); + assertAddress(server.getLocalAddress(), address, "server"); + assertAddress(client.getRemoteAddress(), address, "client"); + Files.delete(address.getPath()); + }); + + // implicit server bind + checkNormal(() -> { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(null); + UnixDomainSocketAddress usa = (UnixDomainSocketAddress)server.getLocalAddress(); + client = SocketChannel.open(usa); + accept1 = server.accept(); + assertAddress(client.getRemoteAddress(), usa, "server"); + Files.delete(usa.getPath()); + }); + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/IOExchanges.java b/test/jdk/java/nio/channels/unixdomain/IOExchanges.java new file mode 100644 index 00000000000..96478b2b20f --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/IOExchanges.java @@ -0,0 +1,1243 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @run testng/othervm IOExchanges + */ + +import java.io.IOException; +import java.net.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.nio.file.Files; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.lang.System.out; +import static java.net.StandardProtocolFamily.*; +import static java.nio.channels.SelectionKey.OP_ACCEPT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class IOExchanges { + static boolean unixDomainSupported = true; + + + @BeforeTest() + public void setup() { + try { + SocketChannel.open(UNIX); + } catch (IOException | UnsupportedOperationException e) { + unixDomainSupported = false; + out.println("Unix domain channels not supported"); + } + } + + static SocketChannel openSocketChannel(ProtocolFamily family) + throws IOException { + return family == UNIX ? SocketChannel.open(family) + : SocketChannel.open(); + } + + static ServerSocketChannel openServerSocketChannel(ProtocolFamily family) + throws IOException { + return family == UNIX ? ServerSocketChannel.open(family) + : ServerSocketChannel.open(); + } + + public static void deleteFile(SocketAddress addr) throws Exception { + if (addr instanceof UnixDomainSocketAddress) { + Files.deleteIfExists(((UnixDomainSocketAddress) addr).getPath()); + } + } + + /* + The following, non-exhaustive set, of tests exercise different combinations + of blocking and non-blocking accept/connect calls along with I/O + operations, that exchange a single byte. The intent it to test a reasonable + set of blocking and non-blocking scenarios. + + The individual test method names follow their test scenario. + [BAccep|SELNBAccep|SPINNBAccep] - Accept either: + blocking, select-non-blocking, spinning-non-blocking + [BConn|NBConn] - blocking connect / non-blocking connect + [BIO|NBIO] - blocking / non-blocking I/O operations (read/write) + [WR|RW] - connecting thread write/accepting thread reads first, and vice-versa + [Id] - unique test Id + + BAccep_BConn_BIO_WR_1 + BAccep_BConn_BIO_RW_2 + SELNBAccep_BConn_BIO_WR_3 + SELNBAccep_BConn_BIO_RW_4 + SPINNBAccep_BConn_BIO_WR_5 + SPINNBAccep_BConn_BIO_RW_6 + BAccep_NBConn_BIO_WR_7 + BAccep_NBConn_BIO_RW_8 + SELNBAccep_NBConn_BIO_WR_9 + SELNBAccep_NBConn_BIO_RW_10 + SPINNBAccep_NBConn_BIO_WR_11 + SPINNBAccep_NBConn_BIO_RW_12 + + BAccep_BConn_NBIO_WR_1a // Non-Blocking I/O + BAccep_BConn_NBIO_RW_2a + SELNBAccep_BConn_NBIO_WR_3a + SELNBAccep_BConn_NBIO_RW_4a + SPINNBAccep_BConn_NBIO_WR_5a + SPINNBAccep_BConn_NBIO_RW_6a + BAccep_NBConn_NBIO_WR_7a + BAccep_NBConn_NBIO_RW_8a + SELNBAccep_NBConn_NBIO_WR_9a + SELNBAccep_NBConn_NBIO_RW_10a + SPINBAccep_NBConn_NBIO_WR_11a + SPINBAccep_NBConn_NBIO_RW_12a + */ + + @DataProvider(name = "family") + public Object[][] family() { + return unixDomainSupported ? + new Object[][] { + { UNIX }, + { INET }} + : new Object[][] { + { INET } + }; + } + + @Test(dataProvider = "family") + public void BAccep_BConn_BIO_WR_1(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t1", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x01).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + } + }); + t.start(); + + try (SocketChannel sc = ssc.accept()) { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x01); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void BAccep_BConn_BIO_RW_2(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t2", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x02); + } + }); + t.start(); + + try (SocketChannel sc = ssc.accept()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x02).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_BConn_BIO_WR_3(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family); + Selector selector = Selector.open()) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t3", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x03).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + } + }); + t.start(); + + ssc.configureBlocking(false).register(selector, OP_ACCEPT); + assertEquals(selector.select(), 1); + + try (SocketChannel sc = ssc.accept()) { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x03); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_BConn_BIO_RW_4(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family); + Selector selector = Selector.open()) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t4", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x04); + } + }); + t.start(); + + ssc.configureBlocking(false).register(selector, OP_ACCEPT); + assertEquals(selector.select(), 1); + + try (SocketChannel sc = ssc.accept()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x04).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_BConn_BIO_WR_5(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t5", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x05).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + } + }); + t.start(); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc = accepted) { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x05); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_BConn_BIO_RW_6(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t6", () -> { + try (SocketChannel sc = openSocketChannel(family)) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x06); + } + }); + t.start(); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc = accepted) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x06).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + // Similar to the previous six scenarios, but with same-thread + // non-blocking connect. + + @Test(dataProvider = "family") + public void BAccep_NBConn_BIO_WR_7(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t7", () -> { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x07).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc2.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x07); + sc2.shutdownOutput(); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void BAccep_NBConn_BIO_RW_8(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t8", () -> { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x08); + sc.shutdownOutput(); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x08).flip(); + assertEquals(sc2.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc2.read(bb.clear()), -1); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_NBConn_BIO_WR_9(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + sc.configureBlocking(false); + sc.connect(addr); + + ssc.configureBlocking(false).register(selector, OP_ACCEPT); + assertEquals(selector.select(), 1); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t9", () -> { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x09).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc2.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x09); + sc2.shutdownOutput(); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_NBConn_BIO_RW_10(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + sc.configureBlocking(false); + sc.connect(addr); + + ssc.configureBlocking(false).register(selector, OP_ACCEPT); + assertEquals(selector.select(), 1); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t10", () -> { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x10); + sc.shutdownOutput(); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x10).flip(); + assertEquals(sc2.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc2.read(bb.clear()), -1); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_NBConn_BIO_WR_11(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc2 = accepted) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t11", () -> { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x11).flip(); + assertEquals(sc.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc.read(bb.clear()), -1); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc2.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x11); + sc2.shutdownOutput(); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_NBConn_BIO_RW_12(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc2 = accepted) { + assertTrue(sc.finishConnect()); + sc.configureBlocking(true); + TestThread t = TestThread.of("t12", () -> { + ByteBuffer bb = ByteBuffer.allocate(10); + assertEquals(sc.read(bb), 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x12); + sc.shutdownOutput(); + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x12).flip(); + assertEquals(sc2.write(bb), 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + assertEquals(sc2.read(bb.clear()), -1); + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + // --- + // Similar to the previous twelve scenarios but with non-blocking IO + // --- + + @Test(dataProvider = "family") + public void BAccep_BConn_NBIO_WR_1a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t1a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x1A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + try (SocketChannel sc = ssc.accept(); + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x1A); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void BAccep_BConn_NBIO_RW_2a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t2a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x2A); + } + }); + t.start(); + + try (SocketChannel sc = ssc.accept(); + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x2A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_BConn_NBIO_WR_3a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family); + Selector aselector = Selector.open()) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t3a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x3A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + ssc.configureBlocking(false).register(aselector, OP_ACCEPT); + assertEquals(aselector.select(), 1); + + try (SocketChannel sc = ssc.accept(); + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x3A); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_BConn_NBIO_RW_4a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family); + Selector aselector = Selector.open()) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t4a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x4A); + } + }); + t.start(); + + ssc.configureBlocking(false).register(aselector, OP_ACCEPT); + assertEquals(aselector.select(), 1); + + try (SocketChannel sc = ssc.accept(); + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x4A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_BConn_NBIO_WR_5a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t5a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x5A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc = accepted; + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x5A); + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINNBAccep_BConn_NBIO_RW_6a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + TestThread t = TestThread.of("t6a", () -> { + try (SocketChannel sc = openSocketChannel(family); + Selector selector = Selector.open()) { + assertTrue(sc.connect(addr)); + ByteBuffer bb = ByteBuffer.allocate(10); + sc.configureBlocking(false); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x6A); + } + }); + t.start(); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc = accepted; + Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x6A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + + } + t.awaitCompletion(); + deleteFile(addr); + } + } + + // Similar to the previous six scenarios but with same-thread + // non-blocking connect. + + @Test(dataProvider = "family") + public void BAccep_NBConn_NBIO_WR_7a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t7a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x7A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + sc2.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), 0x7A); + sc2.shutdownOutput(); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void BAccep_NBConn_NBIO_RW_8a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t8a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), (byte) 0x8A); + sc.shutdownOutput(); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x8A).flip(); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + SelectionKey k = sc2.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc2.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, -1); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + Selector aselector = Selector.open(); + ssc.configureBlocking(false).register(aselector, OP_ACCEPT); + assertEquals(aselector.select(), 1); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t9a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x9A).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + sc2.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), (byte) 0x9A); + sc2.shutdownOutput(); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + Selector aselector = Selector.open(); + ssc.configureBlocking(false).register(aselector, OP_ACCEPT); + assertEquals(aselector.select(), 1); + + try (SocketChannel sc2 = ssc.accept()) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t10a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), (byte) 0xAA); + sc.shutdownOutput(); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0xAA).flip(); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + SelectionKey k = sc2.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc2.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, -1); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINBAccep_NBConn_NBIO_WR_11a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc2 = accepted) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t11a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0xBA).flip(); + sc.configureBlocking(false); + SelectionKey k = sc.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, -1); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + sc2.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), (byte) 0xBA); + sc2.shutdownOutput(); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + @Test(dataProvider = "family") + public void SPINBAccep_NBConn_NBIO_RW_12a(ProtocolFamily family) + throws Throwable { + try (ServerSocketChannel ssc = openServerSocketChannel(family)) { + ssc.bind(null); + SocketAddress addr = ssc.getLocalAddress(); + + try (SocketChannel sc = openSocketChannel(family)) { + sc.configureBlocking(false); + sc.connect(addr); + + SocketChannel accepted; + for (; ; ) { + accepted = ssc.accept(); + if (accepted != null) { + out.println("accepted new connection"); + break; + } + Thread.onSpinWait(); + } + + try (SocketChannel sc2 = accepted) { + assertTrue(sc.finishConnect()); + TestThread t = TestThread.of("t10a", () -> { + try (Selector selector = Selector.open()) { + ByteBuffer bb = ByteBuffer.allocate(10); + sc.register(selector, OP_READ); + selector.select(); + int c; + while ((c = sc.read(bb)) == 0) ; + assertEquals(c, 1); + out.printf("read: 0x%x%n", bb.get(0)); + assertEquals(bb.get(0), (byte) 0xCA); + sc.shutdownOutput(); + } + }); + t.start(); + + ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0xCA).flip(); + sc2.configureBlocking(false); + try (Selector selector = Selector.open()) { + SelectionKey k = sc2.register(selector, OP_WRITE); + selector.select(); + int c; + while ((c = sc2.write(bb)) < 1) ; + assertEquals(c, 1); + out.printf("wrote: 0x%x%n", bb.get(0)); + k.interestOps(OP_READ); + selector.select(); + bb.clear(); + while ((c = sc2.read(bb)) == 0) ; + assertEquals(c, -1); + } + t.awaitCompletion(); + } + } + deleteFile(addr); + } + } + + // -- + + static class TestThread extends Thread { + private final UncheckedRunnable runnable; + private volatile Throwable throwable; + + TestThread(UncheckedRunnable runnable, String name) { + super(name); + this.runnable = runnable; + } + + @Override + public void run() { + try { + runnable.run(); + } catch (Throwable t) { + out.printf("[%s] caught unexpected: %s%n", getName(), t); + throwable = t; + } + } + + interface UncheckedRunnable { + void run() throws Throwable; + } + + static TestThread of(String name, UncheckedRunnable runnable) { + return new TestThread(runnable, name); + } + + void awaitCompletion() throws Throwable { + this.join(); + if (throwable != null) + throw throwable; + } + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/NonBlockingAccept.java b/test/jdk/java/nio/channels/unixdomain/NonBlockingAccept.java new file mode 100644 index 00000000000..62b21a98d60 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/NonBlockingAccept.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @library /test/lib + * @run main/othervm NonBlockingAccept + */ + +import java.net.StandardProtocolFamily; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import jtreg.SkippedException; + +public class NonBlockingAccept { + + static void checkSupported() { + try { + SocketChannel.open(StandardProtocolFamily.UNIX).close(); + } catch (UnsupportedOperationException e) { + throw new SkippedException("Unix domain sockets not supported"); + } catch (Exception e) { + // continue + } + } + + public static void main(String[] args) throws Exception { + + checkSupported(); + + try (ServerSocketChannel serverSocketChannel = + ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + //non blocking mode + serverSocketChannel.configureBlocking(false); + serverSocketChannel.bind(null); + SocketChannel socketChannel = serverSocketChannel.accept(); + System.out.println("The socketChannel is : expected Null " + socketChannel); + if (socketChannel != null) + throw new RuntimeException("expected null"); + // or exception could be thrown otherwise + } + } +} + diff --git a/test/jdk/java/nio/channels/unixdomain/NullTest.java b/test/jdk/java/nio/channels/unixdomain/NullTest.java new file mode 100644 index 00000000000..ed96cfdecc9 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/NullTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @run testng NullTest + */ + +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.*; +import java.nio.file.Path; +import org.testng.annotations.Test; +import static org.testng.Assert.assertThrows; + +/** + * Check for NPE + */ +public class NullTest { + + // Expected exception + private static final Class NPE = + NullPointerException.class; + + @Test + public static void runTest() throws Exception { + assertThrows(NPE, () -> SocketChannel.open((ProtocolFamily)null)); + assertThrows(NPE, () -> SocketChannel.open((SocketAddress)null)); + assertThrows(NPE, () -> ServerSocketChannel.open((ProtocolFamily)null)); + assertThrows(NPE, () -> UnixDomainSocketAddress.of((Path)null)); + assertThrows(NPE, () -> UnixDomainSocketAddress.of((String)null)); + } + +} diff --git a/test/jdk/java/nio/channels/unixdomain/Security.java b/test/jdk/java/nio/channels/unixdomain/Security.java new file mode 100644 index 00000000000..2bba0e32af3 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/Security.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @run main/othervm/java.security.policy=policy1 Security policy1 + * @run main/othervm/java.security.policy=policy2 Security policy2 + * @run main/othervm Security policy3 + * @summary Security test for Unix Domain socket and server socket channels + */ + +import java.io.File; +import java.io.IOException; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; + +import static java.net.StandardProtocolFamily.UNIX; + +/** + * Tests required all with security manager + */ + +public class Security { + + static interface Command { + public void run() throws Exception; + } + + static void call(Command r, Class expectedException) { + boolean threw = false; + try { + r.run(); + } catch (Throwable t) { + if (expectedException == null) { + t.printStackTrace(); + throw new RuntimeException("an exception was thrown but was not expected"); + } + threw = true; + if (!(expectedException.isAssignableFrom(t.getClass()))) { + throw new RuntimeException("wrong exception type thrown " + t.toString()); + } + } + if (expectedException != null && !threw) { + // should have thrown + throw new RuntimeException("% was expected".formatted(expectedException.getName())); + } + } + + + public static void main(String[] args) throws Exception { + try { + SocketChannel.open(UNIX); + } catch (UnsupportedOperationException e) { + System.out.println("Unix domain not supported"); + return; + } + + String policy = args[0]; + switch (policy) { + case "policy1": + testPolicy1(); + break; + case "policy2": + testPolicy2(); + break; + case "policy3": + testPolicy3(); + break; + } + } + + static void setSecurityManager(String policy) { + String testSrc = System.getProperty("test.src"); + // Three /// required for Windows below + String policyURL = "file:///" + testSrc + File.separator + policy; + System.out.println("POLICY: " + policyURL); + System.setProperty("java.security.policy", policyURL); + System.setSecurityManager(new SecurityManager()); + } + + static void close(NetworkChannel... channels) { + + for (NetworkChannel chan : channels) { + try { + chan.close(); + } catch (Exception e) { + } + } + } + + private static final Class SE = SecurityException.class; + private static final Class IOE = IOException.class; + + // No permission + + public static void testPolicy1() throws Exception { + Path servername = Path.of("sock"); + Files.deleteIfExists(servername); + // Permission exists to bind a ServerSocketChannel + final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(servername); + try (final ServerSocketChannel server = ServerSocketChannel.open(UNIX)) { + try (final SocketChannel client = SocketChannel.open(UNIX)) { + call(() -> { + server.bind(saddr); + }, SE); + call(() -> { + client.connect(saddr); + }, SE); + } + } finally { + Files.deleteIfExists(servername); + } + } + + // All permissions + + public static void testPolicy2() throws Exception { + Path servername = Path.of("sock"); + Files.deleteIfExists(servername); + final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(servername); + try (final ServerSocketChannel server = ServerSocketChannel.open(UNIX)) { + try (final SocketChannel client = SocketChannel.open(UNIX)) { + call(() -> { + server.bind(saddr); + }, null); + call(() -> { + client.connect(saddr); + }, null); + } + } finally { + Files.deleteIfExists(servername); + } + } + + public static void testPolicy3() throws Exception { + Path sock1 = Path.of("sock3"); + Files.deleteIfExists(sock1); + final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(sock1); + try (var s1 = ServerSocketChannel.open(UNIX)) { + s1.bind(saddr); + try (var s2 = ServerSocketChannel.open(UNIX)) { + s2.bind(null); + var add2 = (UnixDomainSocketAddress)s2.getLocalAddress(); + saddr.getPath().toFile().deleteOnExit(); + add2.getPath().toFile().deleteOnExit(); + + // Now set security manager and check if we can see addresses + + setSecurityManager("policy3"); + + if (((UnixDomainSocketAddress)s1 + .getLocalAddress()) + .getPath() + .toString() + .length() != 0) + { + throw new RuntimeException("address should have been empty"); + } + + if (((UnixDomainSocketAddress)s2 + .getLocalAddress()) + .getPath() + .toString() + .length() != 0) + { + throw new RuntimeException("address should have been empty"); + } + } + } + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/Shutdown.java b/test/jdk/java/nio/channels/unixdomain/Shutdown.java new file mode 100644 index 00000000000..acdd9978528 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/Shutdown.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @run main/othervm Shutdown + */ + +import java.io.Closeable; +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Arrays; + +/** + * Check that half close works + */ +public class Shutdown { + + public static void main(String args[]) throws Exception { + if (!supported()) { + System.out.println("Unix domain channels not supported"); + return; + } + runTest(); + } + + static boolean supported() { + try { + SocketChannel.open(StandardProtocolFamily.UNIX).close(); + } catch (UnsupportedOperationException e) { + return false; + } catch (Exception e) { + return true; // continue test to see what problem is + } + return true; + } + + static void assertTrue(boolean condition, String error) { + if (!condition) + throw new RuntimeException(error); + } + + public static void runTest() throws IOException { + ServerSocketChannel server = null; + SocketChannel client = null; + SocketChannel acceptee = null; + UnixDomainSocketAddress usa = null; + + try { + server = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + server.bind(null); + usa = (UnixDomainSocketAddress)server.getLocalAddress(); + System.out.println("Local address " + usa); + client = SocketChannel.open(usa); + acceptee = server.accept(); + ByteBuffer buf = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.ISO_8859_1)); + ByteBuffer rx = ByteBuffer.allocate(buf.capacity()); + client.write(buf); + buf.rewind(); + while (rx.hasRemaining()) + acceptee.read(rx); + + assertTrue(Arrays.equals(buf.array(), rx.array()), "array contents not equal"); + + client.shutdownOutput(); + try { + client.write(buf); + throw new RuntimeException("shutdown error"); + } catch (ClosedChannelException e) { + } + + rx.clear(); + int c = acceptee.read(rx); + assertTrue(c == -1, "read after remote shutdown"); + + client.configureBlocking(false); + c = client.read(rx); + assertTrue(c == 0, "expected c == 0"); + client.shutdownInput(); + c = client.read(rx); + assertTrue(c == -1, "expected c == -1"); + } finally { + close(server); + close(client); + close(acceptee); + if (usa != null) + Files.delete(usa.getPath()); + } + System.out.println("OK"); + } + + static void close(Closeable c) { + try { + if (c != null) + c.close(); + } catch (IOException e) {} + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/SocketOptions.java b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java new file mode 100644 index 00000000000..f275b519394 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8245194 + * @run main/othervm SocketOptions + */ + +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; +import jdk.net.UnixDomainPrincipal; +import static jdk.net.ExtendedSocketOptions.SO_PEERCRED; + +/** + * Check that all supported options can actually be set and got + */ +public class SocketOptions { + + public static void main(String args[]) throws Exception { + if (!supported()) { + System.out.println("Unix domain channels not supported"); + return; + } + test(ServerSocketChannel.open(StandardProtocolFamily.UNIX)); + test(SocketChannel.open(StandardProtocolFamily.UNIX)); + testPeerCred(); + } + + static void testPeerCred() throws Exception { + UnixDomainSocketAddress addr = null; + UnixDomainPrincipal p; + try (ServerSocketChannel s = ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + s.bind(null); + addr = (UnixDomainSocketAddress)s.getLocalAddress(); + try (SocketChannel c = SocketChannel.open(addr)) { + if (!c.supportedOptions().contains(SO_PEERCRED)) { + return; + } + Files.deleteIfExists(addr.getPath()); + p = c.getOption(SO_PEERCRED); + String s1 = p.user().getName(); + System.out.println(s1); + System.out.println(p.group().getName()); + String s2 = System.getProperty("user.name"); + + // Check returned user name + + if (!s1.equals(s2)) { + throw new RuntimeException("wrong username"); + } + + // Try setting the option: Read only + + try { + c.setOption(SO_PEERCRED, p); + throw new RuntimeException("should have thrown SocketException"); + } catch (SocketException e) {} + } + } finally { + if (addr != null) + Files.deleteIfExists(addr.getPath()); + } + + // Try getting from unconnected socket + + try (var c = SocketChannel.open(StandardProtocolFamily.UNIX)) { + try { + p = c.getOption(SO_PEERCRED); + System.out.println(p.user()); + throw new RuntimeException("should have thrown SocketException"); + } catch (SocketException e) {} + } + + // Try getting from ServerSocketChannel + + try (var server = ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + try { + p = server.getOption(SO_PEERCRED); + System.out.println(p.user()); + throw new RuntimeException("should have thrown USE"); + } catch (UnsupportedOperationException e) {} + } + } + + static boolean supported() { + try { + SocketChannel.open(StandardProtocolFamily.UNIX).close(); + } catch (UnsupportedOperationException e) { + return false; + } catch (Exception e) { + return true; // continue test to see what problem is + } + return true; + } + + @SuppressWarnings("unchecked") + public static void test(NetworkChannel chan) throws IOException { + System.out.println("Checking: " + chan.getClass()); + Set> supported = chan.supportedOptions(); + for (SocketOption option : supported) { + String name = option.name(); + System.out.println("Checking option " + name); + if (option.type() == Boolean.class) { + chan.setOption((SocketOption)option, true); + chan.setOption((SocketOption)option, false); + chan.getOption(option); + } else if (option.type() == Integer.class) { + chan.setOption((SocketOption)option, 10); + chan.getOption(option); + } + } + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/policy1 b/test/jdk/java/nio/channels/unixdomain/policy1 new file mode 100644 index 00000000000..ccfe2ef15a7 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/policy1 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +grant { + // No permission + permission java.io.FilePermission "sock", "delete"; +}; diff --git a/test/jdk/java/nio/channels/unixdomain/policy2 b/test/jdk/java/nio/channels/unixdomain/policy2 new file mode 100644 index 00000000000..00643294155 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/policy2 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +grant { + // permission to bind a SocketChannel in sockets directory + permission java.net.NetPermission "accessUnixDomainSocket"; + + permission java.io.FilePermission "sock", "delete"; +}; diff --git a/test/jdk/java/nio/channels/unixdomain/policy3 b/test/jdk/java/nio/channels/unixdomain/policy3 new file mode 100644 index 00000000000..ccfe2ef15a7 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/policy3 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +grant { + // No permission + permission java.io.FilePermission "sock", "delete"; +}; diff --git a/test/jdk/java/text/Bidi/BidiConformance.java b/test/jdk/java/text/Bidi/BidiConformance.java index 45e49cb632f..8c359361969 100644 --- a/test/jdk/java/text/Bidi/BidiConformance.java +++ b/test/jdk/java/text/Bidi/BidiConformance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6850113 8032446 + * @bug 6850113 8032446 8255242 * @summary confirm the behavior of new Bidi implementation. (Backward compatibility) * @modules java.desktop */ @@ -1397,6 +1397,12 @@ private void testMethod_requiresBidi() { " when limit is textLength+1(too large)."); } catch (IllegalArgumentException e) { + if (!e.getMessage().equals( + "Value start 0 is out of range 0 to " + (textLength + 1) + + ", or limit " + (textLength + 1) + " is beyond the text length " + textLength)) { + errorHandling("requiresBidi() should throw an IAE" + + " mentioning limit is beyond the text length. Message: " + e.getMessage()); + } } catch (ArrayIndexOutOfBoundsException e) { errorHandling("requiresBidi() should not throw an AIOoBE " + diff --git a/test/jdk/java/util/Formatter/BasicDateTime.java b/test/jdk/java/util/Formatter/BasicDateTime.java index 72f446625b2..5b760960ff0 100644 --- a/test/jdk/java/util/Formatter/BasicDateTime.java +++ b/test/jdk/java/util/Formatter/BasicDateTime.java @@ -1687,6 +1687,17 @@ public static void test() { // Get the supported ids for GMT-08:00 (Pacific Standard Time) String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); + // With tzdata2020b, the test fails for the mentioned zones expecting + // "PST" but JDK has Zone name "MST" for JRE locale provider. + // Therefore excluding them as the test is only looking for a GMT-08:00 + // time zone ID. See JDK-8254865. + final List list = new ArrayList(); + Collections.addAll(list, ids); + list.remove("America/Dawson"); + list.remove("America/WhiteHorse"); + list.remove("Canada/Yukon"); + ids = list.toArray(new String[list.size()]); + // Create a Pacific Standard Time time zone SimpleTimeZone tz = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]); // public GregorianCalendar(TimeZone zone, Locale aLocale); diff --git a/test/jdk/java/util/Locale/LocaleEnhanceTest.java b/test/jdk/java/util/Locale/LocaleEnhanceTest.java index 7baac43a046..e0a671d5d88 100644 --- a/test/jdk/java/util/Locale/LocaleEnhanceTest.java +++ b/test/jdk/java/util/Locale/LocaleEnhanceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ /** * @test * @bug 6875847 6992272 7002320 7015500 7023613 7032820 7033504 7004603 - * 7044019 8008577 8176853 + * 7044019 8008577 8176853 8255086 * @summary test API changes to Locale * @library /java/text/testlib * @modules jdk.localedata @@ -615,7 +615,7 @@ public void testGetDisplayScript() { Locale.setDefault(Locale.US); assertEquals("latn US", "Latin", latnLocale.getDisplayScript()); - assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript()); + assertEquals("hans US", "Simplified", hansLocale.getDisplayScript()); Locale.setDefault(Locale.GERMANY); assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript()); @@ -629,7 +629,7 @@ public void testGetDisplayScriptWithLocale() { Locale hansLocale = Locale.forLanguageTag("und-hans"); assertEquals("latn US", "Latin", latnLocale.getDisplayScript(Locale.US)); - assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript(Locale.US)); + assertEquals("hans US", "Simplified", hansLocale.getDisplayScript(Locale.US)); assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY)); assertEquals("hans DE", "Vereinfachte Chinesische Schrift", hansLocale.getDisplayScript(Locale.GERMANY)); @@ -656,10 +656,10 @@ public void testGetDisplayName() { "United States", "Norwegian (Norway,Nynorsk)", "Nynorsk", - "Chinese (Simplified Han)", - "Chinese (Traditional Han)", - "Chinese (Simplified Han,China)", - "Simplified Han", + "Chinese (Simplified)", + "Chinese (Traditional)", + "Chinese (Simplified,China)", + "Simplified", }; final String[] displayNameSimplifiedChinese = { diff --git a/test/jdk/java/util/Locale/LocaleTest.java b/test/jdk/java/util/Locale/LocaleTest.java index f80296bd680..c571fcf63df 100644 --- a/test/jdk/java/util/Locale/LocaleTest.java +++ b/test/jdk/java/util/Locale/LocaleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613 * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 - * 6786276 7066203 7085757 8008577 8030696 8170840 + * 6786276 7066203 7085757 8008577 8030696 8170840 8255086 * @summary test Locales * @library /java/text/testlib * @modules jdk.localedata @@ -635,7 +635,7 @@ public void TestSimpleDisplayNames() { // names, and other stuff like that. This test just checks specific language // and country codes to make sure we have the correct names for them. String[] languageCodes = {"he", "id", "iu", "ug", "yi", "za"}; - String[] languageNames = {"Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish", + String[] languageNames = {"Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish", "Zhuang"}; for (int i = 0; i < languageCodes.length; i++) { diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java index 2d2d33d0ab7..c5410865a2b 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java @@ -40,12 +40,12 @@ public class SegmentTestDataProvider { static VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class); - static VarHandle CHAR_HANDLE = MemoryLayouts.JAVA_CHAR.varHandle(char.class); - static VarHandle SHORT_HANDLE = MemoryLayouts.JAVA_SHORT.varHandle(short.class); - static VarHandle INT_HANDLE = MemoryLayouts.JAVA_INT.varHandle(int.class); - static VarHandle LONG_HANDLE = MemoryLayouts.JAVA_LONG.varHandle(long.class); - static VarHandle FLOAT_HANDLE = MemoryLayouts.JAVA_FLOAT.varHandle(float.class); - static VarHandle DOUBLE_HANDLE = MemoryLayouts.JAVA_DOUBLE.varHandle(double.class); + static VarHandle CHAR_HANDLE = MemoryLayouts.JAVA_CHAR.withBitAlignment(8).varHandle(char.class); + static VarHandle SHORT_HANDLE = MemoryLayouts.JAVA_SHORT.withBitAlignment(8).varHandle(short.class); + static VarHandle INT_HANDLE = MemoryLayouts.JAVA_INT.withBitAlignment(8).varHandle(int.class); + static VarHandle LONG_HANDLE = MemoryLayouts.JAVA_LONG.withBitAlignment(8).varHandle(long.class); + static VarHandle FLOAT_HANDLE = MemoryLayouts.JAVA_FLOAT.withBitAlignment(8).varHandle(float.class); + static VarHandle DOUBLE_HANDLE = MemoryLayouts.JAVA_DOUBLE.withBitAlignment(8).varHandle(double.class); static boolean compareSegmentsByte(Collection segments1, Collection segments2, boolean isOrdered) { Function mapper = segment -> (byte)BYTE_HANDLE.get(segment.baseAddress()); diff --git a/test/jdk/javax/swing/JMenu/4692443/bug4692443.java b/test/jdk/javax/swing/JMenu/4692443/bug4692443.java index d61da32dc8f..70a007cf51b 100644 --- a/test/jdk/javax/swing/JMenu/4692443/bug4692443.java +++ b/test/jdk/javax/swing/JMenu/4692443/bug4692443.java @@ -50,6 +50,7 @@ public static void main(String args[]) throws Throwable { pass = new PassedListener(); passed = false; Robot robo = new Robot(); + robo.setAutoDelay(100); SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -58,9 +59,9 @@ public void run() { }); robo.waitForIdle(); + robo.delay(1000); int altKey = java.awt.event.KeyEvent.VK_ALT; - robo.setAutoDelay(100); Util.hitMnemonics(robo, KeyEvent.VK_F); // Enter File menu robo.keyPress(KeyEvent.VK_S); // Enter submenu robo.keyRelease(KeyEvent.VK_S); @@ -79,6 +80,7 @@ public void run() { } } + private static void createAndShowGUI() { mainFrame = new JFrame("Bug 4692443"); JMenuBar mbar = new JMenuBar(); @@ -109,7 +111,7 @@ public void menuCanceled(MenuEvent e) { mainFrame.setJMenuBar(mbar); mainFrame.setSize(200, 200); - mainFrame.setLocation(200, 200); + mainFrame.setLocationRelativeTo(null); mainFrame.setVisible(true); mainFrame.toFront(); } diff --git a/test/jdk/javax/swing/JPopupMenu/4458079/bug4458079.java b/test/jdk/javax/swing/JPopupMenu/4458079/bug4458079.java index c68841a1c11..c0d93699a93 100644 --- a/test/jdk/javax/swing/JPopupMenu/4458079/bug4458079.java +++ b/test/jdk/javax/swing/JPopupMenu/4458079/bug4458079.java @@ -44,9 +44,10 @@ public class bug4458079 extends JFrame implements PopupMenuListener { static volatile boolean itemASelected = false; public static void main(String[] args) throws Exception { Robot robot = new Robot(); - robot.waitForIdle(); + robot.setAutoDelay(100); // move mouse outside menu to prevent auto selection robot.mouseMove(100,100); + robot.waitForIdle(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -54,18 +55,16 @@ public void run() { } }); - robot.setAutoDelay(50); - + robot.waitForIdle(); + robot.delay(1000); Util.hitMnemonics(robot, KeyEvent.VK_M); robot.waitForIdle(); - Thread.sleep(1000); Util.hitKeys(robot, KeyEvent.VK_DOWN); Util.hitKeys(robot, KeyEvent.VK_ENTER); robot.waitForIdle(); - Thread.sleep(1000); if (!itemASelected) { throw new RuntimeException("Test failed: arrow key traversal in JMenu broken!"); diff --git a/test/jdk/javax/swing/JPopupMenu/6544309/bug6544309.java b/test/jdk/javax/swing/JPopupMenu/6544309/bug6544309.java index fa0968ff77c..df5178e320c 100644 --- a/test/jdk/javax/swing/JPopupMenu/6544309/bug6544309.java +++ b/test/jdk/javax/swing/JPopupMenu/6544309/bug6544309.java @@ -22,16 +22,13 @@ */ /* @test - @key headful + @key headful @bug 6544309 @summary Checks that 'Select Input Method' popup menu allows to select items with keyboard. - @author Mikhail Lapshin - @library /lib/client - @build ExtendedRobot @run main bug6544309 */ - +import java.awt.Robot; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -44,12 +41,15 @@ public class bug6544309 { private JDialog dialog; private boolean passed; - private static ExtendedRobot robot; + private static Robot robot; public static void main(String[] args) throws Exception { - robot = new ExtendedRobot(); + robot = new Robot(); + robot.setAutoDelay(100); // move mouse outside menu to prevent auto selection robot.mouseMove(100,100); + robot.waitForIdle(); + final bug6544309 test = new bug6544309(); try { SwingUtilities.invokeAndWait(new Runnable() { @@ -57,6 +57,8 @@ public void run() { test.setupUI(); } }); + robot.waitForIdle(); + robot.delay(1000); test.test(); System.out.println("Test passed"); } finally { @@ -95,13 +97,16 @@ private void test() throws Exception { private void testImpl() throws Exception { robot.waitForIdle(); System.out.println("Pressing DOWN ARROW"); - robot.type(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); robot.waitForIdle(); System.out.println("Pressing DOWN ARROW"); - robot.type(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); robot.waitForIdle(); System.out.println("Pressing SPACE"); - robot.type(KeyEvent.VK_SPACE); + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); } private void checkResult() { diff --git a/test/jdk/javax/swing/JPopupMenu/6827786/bug6827786.java b/test/jdk/javax/swing/JPopupMenu/6827786/bug6827786.java index 7d046b6123e..3f2d58edcad 100644 --- a/test/jdk/javax/swing/JPopupMenu/6827786/bug6827786.java +++ b/test/jdk/javax/swing/JPopupMenu/6827786/bug6827786.java @@ -49,9 +49,10 @@ public class bug6827786 { public static void main(String[] args) throws Exception { try { Robot robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); // move mouse outside menu to prevent auto selection - robot.mouseMove(100,100); + robot.mouseMove(100,100); + robot.waitForIdle(); SwingUtilities.invokeAndWait(new Runnable() { @@ -61,6 +62,7 @@ public void run() { }); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(new Runnable() { diff --git a/test/jdk/javax/swing/JTabbedPane/7024235/Test7024235.java b/test/jdk/javax/swing/JTabbedPane/7024235/Test7024235.java index 090c47e2808..5cd1019a835 100644 --- a/test/jdk/javax/swing/JTabbedPane/7024235/Test7024235.java +++ b/test/jdk/javax/swing/JTabbedPane/7024235/Test7024235.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,16 +22,14 @@ */ import java.awt.BorderLayout; - import java.awt.Container; import java.awt.Rectangle; -import java.awt.Toolkit; +import java.awt.Robot; import javax.swing.JButton; import javax.swing.JCheckBox; -import javax.swing.JTabbedPane; - import javax.swing.JFrame; +import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; @@ -41,9 +39,6 @@ * @key headful * @bug 7024235 * @summary Tests JFrame.pack() with the JTabbedPane - * @library /lib/client/ - * @build ExtendedRobot - * @author Sergey Malenkov * @run main Test7024235 */ @@ -54,12 +49,15 @@ public class Test7024235 implements Runnable { public static void main(String[] args) throws Exception { Test7024235 test = new Test7024235(); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - UIManager.setLookAndFeel(info.getClassName()); + String className = info.getClassName(); + System.out.println("className = " + className); + UIManager.setLookAndFeel(className); test.test(); try { - ExtendedRobot robot = new ExtendedRobot(); - robot.waitForIdle(1000); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); }catch(Exception ex) { ex.printStackTrace(); throw new Error("Unexpected Failure"); @@ -81,6 +79,7 @@ public void run() { JFrame frame = new JFrame(); frame.add(BorderLayout.WEST, this.pane); frame.pack(); + frame.setLocationRelativeTo(null); frame.setVisible(true); test("first"); @@ -105,6 +104,9 @@ private void test(String step) { this.passed = true; for (int index = 0; index < this.pane.getTabCount(); index++) { Rectangle bounds = this.pane.getBoundsAt(index); + if (bounds == null) { + continue; + } int centerX = bounds.x + bounds.width / 2; int centerY = bounds.y + bounds.height / 2; int actual = this.pane.indexAtLocation(centerX, centerY); diff --git a/test/jdk/javax/swing/SpringLayout/4726194/bug4726194.java b/test/jdk/javax/swing/SpringLayout/4726194/bug4726194.java index 5199be566c2..048961089c4 100644 --- a/test/jdk/javax/swing/SpringLayout/4726194/bug4726194.java +++ b/test/jdk/javax/swing/SpringLayout/4726194/bug4726194.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,22 @@ * @test * @bug 4726194 7124209 * @summary Tests for 4726194 - * @author Phil Milne */ -import java.awt.*; -import java.lang.reflect.InvocationTargetException; -import java.util.*; + +import java.awt.Font; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import javax.swing.*; + +import javax.swing.BorderFactory; +import javax.swing.JTextField; +import javax.swing.Spring; +import javax.swing.SpringLayout; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; public class bug4726194 { @@ -40,22 +49,29 @@ public class bug4726194 { private static int[] FAIL = new int[3]; private static boolean TEST_DUPLICATES = false; - public static void main(String[] args) { - try { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - int minLevel = 2; - int maxLevel = 2; - for (int i = minLevel; i <= maxLevel; i++) { - test(i, true); - test(i, false); - } + public static void main(String[] args) throws Exception { + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(() -> { + int minLevel = 2; + int maxLevel = 2; + for (int i = minLevel; i <= maxLevel; i++) { + test(i, true); + test(i, false); } }); - } catch (InterruptedException | InvocationTargetException ex) { - ex.printStackTrace(); - throw new RuntimeException("FAILED: SwingUtilities.invokeAndWait method failed!"); + } + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + System.out.println("LookAndFeel: " + laf.getClassName()); + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored){ + System.out.println("Unsupported LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + IllegalAccessException e) { + throw new RuntimeException(e); } } @@ -64,6 +80,7 @@ public static void test(int level, boolean horizontal) { String[] constraints = horizontal ? hConstraints : vConstraints; test(level, constraints, result, Arrays.asList(new Object[level])); JTextField tf = new JTextField(""); + tf.setBorder(BorderFactory.createEmptyBorder()); tf.setFont(new Font("Dialog", Font.PLAIN, 6)); System.out.print("\t\t"); for (int j = 0; j < constraints.length; j++) { diff --git a/test/jdk/javax/swing/ToolTipManager/Test6256140.java b/test/jdk/javax/swing/ToolTipManager/Test6256140.java index 3456c0ecec8..641d58ac09e 100644 --- a/test/jdk/javax/swing/ToolTipManager/Test6256140.java +++ b/test/jdk/javax/swing/ToolTipManager/Test6256140.java @@ -40,49 +40,58 @@ public class Test6256140 { private final static String initialText = "value"; private final static JLabel toolTipLabel = new JLabel("tip"); + private static JFrame frame; public static void main(String[] args) throws Exception { - - Robot robot = new Robot(); - robot.setAutoDelay(10); - - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - createAndShowGUI(); + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + robot.waitForIdle(); + robot.delay(1000); + + Point point = ft.getLocationOnScreen(); + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + robot.mouseMove(point.x + 3, point.y + 3); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + + if (!isTooltipShowning()) { + throw new RuntimeException("Tooltip is not shown"); } - }); - robot.waitForIdle(); - - Point point = ft.getLocationOnScreen(); - robot.mouseMove(point.x, point.y); - robot.mouseMove(point.x + 3, point.y + 3); - robot.keyPress(KeyEvent.VK_A); - robot.keyRelease(KeyEvent.VK_A); - robot.waitForIdle(); - - if (!isTooltipShowning()) { - throw new RuntimeException("Tooltip is not shown"); - } + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_ESCAPE); - robot.keyRelease(KeyEvent.VK_ESCAPE); - robot.waitForIdle(); - - if (isTooltipShowning()) { - throw new RuntimeException("Tooltip must be hidden now"); - } + if (isTooltipShowning()) { + throw new RuntimeException("Tooltip must be hidden now"); + } - if (isTextEqual()) { - throw new RuntimeException("FormattedTextField must *not* cancel the updated value this time"); - } + if (isTextEqual()) { + throw new RuntimeException("FormattedTextField must *not* cancel the updated value this time"); + } - robot.keyPress(KeyEvent.VK_ESCAPE); - robot.keyRelease(KeyEvent.VK_ESCAPE); - robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); - if (!isTextEqual()) { - throw new RuntimeException("FormattedTextField must cancel the updated value"); + if (!isTextEqual()) { + throw new RuntimeException("FormattedTextField must cancel the updated value"); + } + } finally { + if (frame != null) { + SwingUtilities.invokeAndWait(frame::dispose); + } } } @@ -116,7 +125,7 @@ private static void createAndShowGUI() { ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE); ToolTipManager.sharedInstance().setInitialDelay(0); - final JFrame frame = new JFrame(); + frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new FlowLayout()); diff --git a/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java b/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java index a4c7c2d8641..e67d2ddb588 100644 --- a/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java +++ b/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,12 +62,6 @@ public void run() { robo.waitForIdle(); area.setCaretPosition(0); - - if ("Aqua".equals(UIManager.getLookAndFeel().getID())) { - Util.hitKeys(robo, KeyEvent.VK_HOME); - } else { - Util.hitKeys(robo, KeyEvent.VK_CONTROL, KeyEvent.VK_HOME); - } robo.waitForIdle(); passed &= moveCaret(true) == 1; @@ -152,6 +146,7 @@ private static void createAndShowGUI() { frame = new JFrame(); frame.setTitle("Bug# 4278839"); frame.setSize(200, 200); + frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); area = new JTextArea("\naaa bbb\nccc ddd\n"); frame.getContentPane().add(new JScrollPane(area)); diff --git a/test/jdk/javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java b/test/jdk/javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java index 8184b6a9562..cdce0dab584 100644 --- a/test/jdk/javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java +++ b/test/jdk/javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java @@ -26,9 +26,6 @@ * @key headful * @bug 5043626 * @summary Tests pressing Home or Ctrl+Home set cursor to invisible element - * @author Alexander Potochkin - * @library ../../../../regtesthelpers - * @build Util * @run main bug5043626 */ @@ -43,38 +40,51 @@ public class bug5043626 { private static Document doc; private static Robot robot; + private static JFrame frame; public static void main(String[] args) throws Exception { - robot = new Robot(); + try { + robot = new Robot(); + robot.setAutoDelay(100); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); - robot.waitForIdle(); + robot.waitForIdle(); + robot.delay(1000); - Util.hitKeys(robot, KeyEvent.VK_HOME); - Util.hitKeys(robot, KeyEvent.VK_1); + robot.keyPress(KeyEvent.VK_HOME); + robot.keyRelease(KeyEvent.VK_HOME); + robot.keyPress(KeyEvent.VK_1); + robot.keyRelease(KeyEvent.VK_1); - robot.waitForIdle(); + robot.waitForIdle(); - String test = getText(); + String test = getText(); - if (!"1test".equals(test)) { - throw new RuntimeException("Begin line action set cursor inside tag"); - } + if (!"1test".equals(test)) { + throw new RuntimeException("Begin line action set cursor inside tag"); + } - Util.hitKeys(robot, KeyEvent.VK_HOME); - Util.hitKeys(robot, KeyEvent.VK_2); + robot.keyPress(KeyEvent.VK_HOME); + robot.keyRelease(KeyEvent.VK_HOME); + robot.keyPress(KeyEvent.VK_2); + robot.keyRelease(KeyEvent.VK_2); - robot.waitForIdle(); + robot.waitForIdle(); - test = getText(); + test = getText(); - if (!"21test".equals(test)) { - throw new RuntimeException("Begin action set cursor inside tag"); + if (!"21test".equals(test)) { + throw new RuntimeException("Begin action set cursor inside tag"); + } + } finally { + if (frame != null) { + SwingUtilities.invokeAndWait(frame::dispose); + } } } @@ -95,7 +105,7 @@ public void run() { } private static void createAndShowGUI() { - JFrame frame = new JFrame(); + frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JEditorPane editorPane = new JEditorPane(); @@ -104,6 +114,7 @@ private static void createAndShowGUI() { editorPane.setEditable(true); frame.add(editorPane); frame.pack(); + frame.setLocationRelativeTo(null); frame.setVisible(true); doc = editorPane.getDocument(); editorPane.setCaretPosition(doc.getLength()); diff --git a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java index 08d85f02bd3..83e86ea3736 100644 --- a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java +++ b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java @@ -800,20 +800,41 @@ static byte[] castByteArrayData(byte[] data, Class atype, Class btype) { int count = data.length / asize; assert(data.length == count * asize); byte[] result = new byte[count * bsize]; - int rp = 0, dp = 0; + int minsize = Math.min(asize, bsize); + int size_diff = bsize - asize; + ByteOrder bo = ByteOrder.nativeOrder(); + int rp = 0, dp = 0; for (int i = 0; i < count; i++) { - int nextrp = rp + bsize; + if (bo == ByteOrder.BIG_ENDIAN) { + if (size_diff > 0) { + byte sign = (byte)(data[dp] >> 7); // sign extend + for (int j = 0; j < size_diff; j++) { + result[rp++] = sign; + } + } else { + dp -= size_diff; // step forward if needed + } + } byte b = 0; - for (int j = 0; j < asize; j++) { + for (int j = 0; j < minsize; j++) { b = data[dp++]; - if (j < minsize) result[rp++] = b; + result[rp++] = b; + } + if (bo == ByteOrder.LITTLE_ENDIAN) { + if (size_diff > 0) { + byte sign = (byte)(b >> 7); // sign extend + for (int j = 0; j < size_diff; j++) { + result[rp++] = sign; + } + } else { + dp -= size_diff; // step forward if needed + } } - b >>= 7; // sign extend - while (rp < nextrp) result[rp++] = b; } assert(dp == data.length); assert(rp == result.length); + return result; } diff --git a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java index e8597bb4dd8..62b3d70ca58 100644 --- a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java +++ b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java @@ -50,6 +50,8 @@ public class TestCgroupSubsystemFactory { private Path existingDirectory; + private Path cgroupv1CgroupsJoinControllers; + private Path cgroupv1MountInfoJoinControllers; private Path cgroupv1CgInfoZeroHierarchy; private Path cgroupv1MntInfoZeroHierarchy; private Path cgroupv2CgInfoZeroHierarchy; @@ -57,7 +59,24 @@ public class TestCgroupSubsystemFactory { private Path cgroupv1CgInfoNonZeroHierarchy; private Path cgroupv1MntInfoNonZeroHierarchy; private Path cgroupv1MntInfoSystemdOnly; + private Path cgroupv1MntInfoDoubleCpusets; + private Path cgroupv1MntInfoDoubleCpusets2; private String mntInfoEmpty = ""; + private String cgroupsNonZeroJoinControllers = + "#subsys_name hierarchy num_cgroups enabled\n" + + "cpuset\t3\t1\t1\n" + + "cpu\t4\t153\t1\n" + + "cpuacct\t4\t153\t1\n" + + "blkio\t7\t87\t1\n" + + "memory\t4\t153\t1\n" + + "devices\t6\t87\t1\n" + + "freezer\t9\t1\t1\n" + + "net_cls\t4\t153\t1\n" + + "perf_event\t2\t1\t1\n" + + "net_prio\t4\t153\t1\n" + + "hugetlb\t4\t153\t1\n" + + "pids\t5\t95\t1\n" + + "rdma\t8\t1\t1\n"; private String cgroupsZeroHierarchy = "#subsys_name hierarchy num_cgroups enabled\n" + "cpuset 0 1 1\n" + @@ -71,18 +90,30 @@ public class TestCgroupSubsystemFactory { "perf_event 0 1 1 "; private String mntInfoHybrid = "30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n" + - "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup2 rw,seclabel,nsdelegate\n" + - "32 30 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,seclabel,xattr,name=systemd\n" + - "35 30 0:31 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,seclabel,memory\n" + - "36 30 0:32 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,seclabel,pids\n" + - "37 30 0:33 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:9 - cgroup cgroup rw,seclabel,perf_event\n" + - "38 30 0:34 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,net_cls,net_prio\n" + - "39 30 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,seclabel,hugetlb\n" + - "40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,seclabel,cpu,cpuacct\n" + - "41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,seclabel,devices\n" + - "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,seclabel,cpuset\n" + - "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,seclabel,blkio\n" + - "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,seclabel,freezer"; + "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n" + + "32 30 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup none rw,seclabel,xattr,name=systemd\n" + + "35 30 0:31 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:7 - cgroup none rw,seclabel,memory\n" + + "36 30 0:32 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:8 - cgroup none rw,seclabel,pids\n" + + "37 30 0:33 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:9 - cgroup none rw,seclabel,perf_event\n" + + "38 30 0:34 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:10 - cgroup none rw,seclabel,net_cls,net_prio\n" + + "39 30 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:11 - cgroup none rw,seclabel,hugetlb\n" + + "40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup none rw,seclabel,cpu,cpuacct\n" + + "41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup none rw,seclabel,devices\n" + + "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" + + "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" + + "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n"; + private String mntInfoCgroupv1JoinControllers = + "31 22 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755\n" + + "32 31 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate\n" + + "33 31 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd\n" + + "36 31 0:31 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,perf_event\n" + + "37 31 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,cpuset\n" + + "38 31 0:33 / /sys/fs/cgroup/cpu,cpuacct,net_cls,net_prio,hugetlb,memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,cpu,cpuacct,memory,net_cls,net_prio,hugetlb\n" + + "39 31 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,pids\n" + + "40 31 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,devices\n" + + "41 31 0:36 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,blkio\n" + + "42 31 0:37 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,rdma\n" + + "43 31 0:38 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,freezer\n"; private String cgroupsNonZeroHierarchy = "#subsys_name hierarchy num_cgroups enabled\n" + "cpuset 9 1 1\n" + @@ -98,10 +129,13 @@ public class TestCgroupSubsystemFactory { "hugetlb 6 1 1\n" + "pids 3 80 1"; private String mntInfoCgroupsV2Only = - "28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup2 rw,seclabel,nsdelegate"; + "28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 none rw,seclabel,nsdelegate"; private String mntInfoCgroupsV1SystemdOnly = "35 26 0:26 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup systemd rw,name=systemd\n" + "26 18 0:19 / /sys/fs/cgroup rw,relatime - tmpfs none rw,size=4k,mode=755\n"; + private String mntInfoCgroupv1MoreCpusetLine = "121 32 0:37 / /cpuset rw,relatime shared:69 - cgroup none rw,cpuset\n"; + private String mntInfoCgroupsV1DoubleCpuset = mntInfoHybrid + mntInfoCgroupv1MoreCpusetLine; + private String mntInfoCgroupsV1DoubleCpuset2 = mntInfoCgroupv1MoreCpusetLine + mntInfoHybrid; @Before public void setup() { @@ -125,6 +159,18 @@ public void setup() { cgroupv1MntInfoSystemdOnly = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv1_systemd_only"); Files.writeString(cgroupv1MntInfoSystemdOnly, mntInfoCgroupsV1SystemdOnly); + + cgroupv1MntInfoDoubleCpusets = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv1_double_cpuset"); + Files.writeString(cgroupv1MntInfoDoubleCpusets, mntInfoCgroupsV1DoubleCpuset); + + cgroupv1MntInfoDoubleCpusets2 = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv1_double_cpuset2"); + Files.writeString(cgroupv1MntInfoDoubleCpusets2, mntInfoCgroupsV1DoubleCpuset2); + + cgroupv1CgroupsJoinControllers = Paths.get(existingDirectory.toString(), "cgroups_cgv1_join_controllers"); + Files.writeString(cgroupv1CgroupsJoinControllers, cgroupsNonZeroJoinControllers); + + cgroupv1MountInfoJoinControllers = Paths.get(existingDirectory.toString(), "mntinfo_cgv1_join_controllers"); + Files.writeString(cgroupv1MountInfoJoinControllers, mntInfoCgroupv1JoinControllers); } catch (IOException e) { throw new RuntimeException(e); } @@ -139,6 +185,17 @@ public void teardown() { } } + @Test + public void testCgroupv1JoinControllerCombo() throws IOException { + String cgroups = cgroupv1CgroupsJoinControllers.toString(); + String mountInfo = cgroupv1MountInfoJoinControllers.toString(); + Optional result = CgroupSubsystemFactory.determineType(mountInfo, cgroups); + + assertTrue("Expected non-empty cgroup result", result.isPresent()); + CgroupTypeResult res = result.get(); + assertFalse("Join controller combination expected as cgroups v1", res.isCgroupV2()); + } + @Test public void testCgroupv1SystemdOnly() throws IOException { String cgroups = cgroupv1CgInfoZeroHierarchy.toString(); @@ -148,6 +205,22 @@ public void testCgroupv1SystemdOnly() throws IOException { assertTrue("zero hierarchy ids with no *relevant* controllers mounted", result.isEmpty()); } + @Test + public void testCgroupv1MultipleCpusetMounts() throws IOException { + doMultipleCpusetMountsTest(cgroupv1MntInfoDoubleCpusets); + doMultipleCpusetMountsTest(cgroupv1MntInfoDoubleCpusets2); + } + + private void doMultipleCpusetMountsTest(Path info) throws IOException { + String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); + String mountInfo = info.toString(); + Optional result = CgroupSubsystemFactory.determineType(mountInfo, cgroups); + + assertTrue("Expected non-empty cgroup result", result.isPresent()); + CgroupTypeResult res = result.get(); + assertFalse("Duplicate cpusets should not influence detection heuristic", res.isCgroupV2()); + } + @Test public void testHybridCgroupsV1() throws IOException { String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); diff --git a/test/jdk/sun/net/ftp/TestFtpTimeValue.java b/test/jdk/sun/net/ftp/TestFtpTimeValue.java new file mode 100644 index 00000000000..e51837db238 --- /dev/null +++ b/test/jdk/sun/net/ftp/TestFtpTimeValue.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8255078 + * @summary verify that datetime in MDTM and MLSD responses are properly parsed + * @library /test/lib + * @modules java.base/sun.net.ftp + * @build jdk.test.lib.Asserts + * @run main/othervm -Duser.timezone=UTC TestFtpTimeValue + * @run main/othervm -Duser.timezone=America/Los_Angeles TestFtpTimeValue + */ + +import jdk.test.lib.Asserts; +import sun.net.ftp.FtpClient; + +import java.io.*; +import java.net.*; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + + +public class TestFtpTimeValue { + private enum TestCase { + AmTimeNoMilli(2019, 4, 20, 10, 57, 13, 0), + AmTimeWithMilli(2019, 4, 20, 10, 57, 13, 50), + PmTimeNoMilli(2019, 4, 20, 22, 57, 13, 0), + PmTimeWithMilli(2019, 4, 20, 22, 57, 13, 50), + ; + + public final Date expectedCreated; + public final Date expectedModified; + public final String create; + public final String modify; + + TestCase(int year, int month, int day, int hrs, int min, int sec, int milliseconds) { + var calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT")); + // month is 0-based in Calendar + calendar.set(year, month - 1, day, hrs, min, sec); + calendar.set(Calendar.MILLISECOND, milliseconds); + expectedCreated = calendar.getTime(); + var s = String.format("%4d%02d%02d%02d%02d%02d", year, month, day, hrs, min, sec); + if (milliseconds != 0) { + s += "." + String.format("%03d", milliseconds); + } + create = s; + + calendar.add(GregorianCalendar.SECOND, 1); + expectedModified = calendar.getTime(); + s = String.format("%4d%02d%02d%02d%02d%02d", year, month, day, hrs, min, sec + 1); + if (milliseconds != 0) { + s += "." + String.format("%03d", milliseconds); + } + modify = s; + } + } + + public static void main(String[] args) throws Exception { + System.out.println("user.timezone: " + System.getProperty("user.timezone")); + try (FtpServer server = new FtpServer(); + FtpClient client = FtpClient.create()) { + (new Thread(server)).start(); + int port = server.getPort(); + var loopback = InetAddress.getLoopbackAddress(); + client.connect(new InetSocketAddress(loopback, port)); + client.enablePassiveMode(true); + for (var testCase : TestCase.values()) { + Asserts.assertEQ(testCase.expectedModified, client.getLastModified(testCase.name()), + "wrong modified date from MDTM for " + testCase); + } + for (var it = client.listFiles(null); it.hasNext(); ) { + var e = it.next(); + Asserts.assertEQ(TestCase.valueOf(e.getName()).expectedCreated, e.getCreated(), + "wrong created date from MLSD for " + e.getName()); + Asserts.assertEQ(TestCase.valueOf(e.getName()).expectedModified, e.getLastModified(), + "wrong modified date from MLSD for " + e.getName()); + } + } + } + + private static class FtpServer implements AutoCloseable, Runnable { + private final ServerSocket serverSocket; + private final ServerSocket pasv; + + FtpServer() throws IOException { + var loopback = InetAddress.getLoopbackAddress(); + serverSocket = new ServerSocket(); + serverSocket.bind(new InetSocketAddress(loopback, 0)); + pasv = new ServerSocket(); + pasv.bind(new InetSocketAddress(loopback, 0)); + } + + public void handleClient(Socket client) throws IOException { + String str; + + client.setSoTimeout(2000); + BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); + PrintWriter out = new PrintWriter(client.getOutputStream(), true); + out.println("220 FTP serverSocket is ready."); + boolean done = false; + while (!done) { + try { + str = in.readLine(); + } catch (SocketException e) { + done = true; + continue; + } + String cmd = str.substring(0, str.indexOf(" ") > 0 ? str.indexOf(" ") : str.length()); + String args = (cmd.equals(str)) ? "" : str.substring(str.indexOf(" ") + 1); + System.err.println("C> " + str); + switch (cmd) { + case "QUIT": + out.println("221 Goodbye."); + System.err.println("S> 221"); + done = true; + break; + case "MDTM": { + var testCase = TestCase.valueOf(args); + out.println("213 " + testCase.modify); + System.err.println("S> 213"); + break; + } + case "MLSD": + try (var socket = pasv.accept(); + var dout = new PrintWriter(socket.getOutputStream(), true)) { + out.println("150 MLSD start"); + System.err.println("S> 150"); + for (var testCase : TestCase.values()) { + dout.printf("modify=%s;create=%s; %s%n", + testCase.modify, testCase.create, testCase.name()); + } + } + out.println("226 MLSD done."); + System.err.println("S> 226"); + break; + case "EPSV": + if ("all".equalsIgnoreCase(args)) { + out.println("200 EPSV ALL command successful."); + System.err.println("S> 200"); + continue; + } + out.println("229 Entering Extended Passive Mode (|||" + pasv.getLocalPort() + "|)"); + System.err.println("S> 229"); + break; + default: + System.err.println("S> 500"); + out.println("500 unsupported command: " + str); + } + } + } + + public int getPort() { + return serverSocket.getLocalPort(); + } + + public void close() throws IOException { + serverSocket.close(); + pasv.close(); + } + + @Override + public void run() { + try (Socket client = serverSocket.accept()) { + handleClient(client); + } catch (Throwable t) { + t.printStackTrace(); + throw new RuntimeException("Problem in test execution", t); + } + } + } +} diff --git a/test/jdk/sun/security/pkcs12/P12SecretKey.java b/test/jdk/sun/security/pkcs12/P12SecretKey.java index 39f95d5e0b1..34c90d638c8 100644 --- a/test/jdk/sun/security/pkcs12/P12SecretKey.java +++ b/test/jdk/sun/security/pkcs12/P12SecretKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,11 @@ /* * @test - * @bug 8149411 + * @bug 8149411 8007632 * @summary Get AES key from keystore (uses SecretKeySpec not SecretKeyFactory) + * @run main P12SecretKey pkcs12 AES 128 + * @run main P12SecretKey pkcs12 DES 56 + * @run main P12SecretKey pkcs12 DESede 168 */ import java.io.File; @@ -43,20 +46,19 @@ public class P12SecretKey { public static void main(String[] args) throws Exception { P12SecretKey testp12 = new P12SecretKey(); - String keystoreType = "pkcs12"; - if (args != null && args.length > 0) { - keystoreType = args[0]; - } - testp12.run(keystoreType); + String keystoreType = args[0]; + String algName = args[1]; + int keySize = Integer.parseInt(args[2]); + testp12.run(keystoreType, algName, keySize); } - private void run(String keystoreType) throws Exception { + private void run(String keystoreType, String algName, int keySize) throws Exception { char[] pw = "password".toCharArray(); KeyStore ks = KeyStore.getInstance(keystoreType); ks.load(null, pw); - KeyGenerator kg = KeyGenerator.getInstance("AES"); - kg.init(128); + KeyGenerator kg = KeyGenerator.getInstance(algName); + kg.init(keySize); SecretKey key = kg.generateKey(); KeyStore.SecretKeyEntry ske = new KeyStore.SecretKeyEntry(key); diff --git a/test/jdk/sun/security/util/DerValue/Indefinite.java b/test/jdk/sun/security/util/DerValue/Indefinite.java index 17270c6642f..989ad4abe02 100644 --- a/test/jdk/sun/security/util/DerValue/Indefinite.java +++ b/test/jdk/sun/security/util/DerValue/Indefinite.java @@ -25,7 +25,7 @@ * @test * @bug 6731685 8249783 * @summary CertificateFactory.generateCertificates throws IOException on PKCS7 cert chain - * @modules java.base/sun.security.util + * @modules java.base/sun.security.util:+open * @library /test/lib */ @@ -35,7 +35,6 @@ import jdk.test.lib.Asserts; import jdk.test.lib.Utils; -import jdk.test.lib.hexdump.HexPrinter; import sun.security.util.*; public class Indefinite { diff --git a/test/jdk/sun/text/resources/LocaleData b/test/jdk/sun/text/resources/LocaleData index 54989fc24f1..bf81b210a71 100644 --- a/test/jdk/sun/text/resources/LocaleData +++ b/test/jdk/sun/text/resources/LocaleData @@ -2399,7 +2399,7 @@ FormatData/ru_RU/NumberPatterns/1=#,##0.## \u00a4;-#,##0.## \u00a4 FormatData/uk_UA/NumberPatterns/1=#,##0.## \u00a4;-#,##0.## \u00a4 # bug #4122468 # Use common country names -LocaleNames//CI=C\u00F4te d'Ivoire +LocaleNames//CI=C\u00F4te d\u2019Ivoire LocaleNames//LY=Libya LocaleNames//RU=Russia LocaleNames//VN=Vietnam @@ -2470,7 +2470,7 @@ FormatData/ko/TimePatterns/3=a h:mm LocaleNames//fo=Faroese LocaleNames//iu=Inuktitut LocaleNames//sg=Sango -LocaleNames//si=Sinhalese +LocaleNames//si=Sinhala #bug 4331446 Localized country and language names for major locales (excerpt only) LocaleNames/es/SV=El Salvador @@ -5468,7 +5468,7 @@ LocaleNames/pt_PT/AX=\u00c5land Islands # JE, GG, IM (6544471) LocaleNames//JE=Jersey LocaleNames//GG=Guernsey -LocaleNames//IM=Isle Of Man +LocaleNames//IM=Isle of Man # bugs 6497154 CalendarData/sk/firstDayOfWeek=2 @@ -5547,11 +5547,11 @@ FormatData/sv/AmPmMarkers/1=em # JE, GG, IM (6544471) LocaleNames//JE=Jersey LocaleNames//GG=Guernsey -LocaleNames//IM=Isle Of Man +LocaleNames//IM=Isle of Man # BL, MF (6627549) -LocaleNames//BL=Saint Barth\u00e9lemy -LocaleNames//MF=Saint Martin +LocaleNames//BL=St. Barth\u00e9lemy +LocaleNames//MF=St. Martin # bug 6609737 FormatData/de/TimePatterns/0=HH:mm' Uhr 'z @@ -8348,3 +8348,114 @@ TimeZoneNames/en/Turkey/1=Turkey Time TimeZoneNames/en/Turkey/2=TRT TimeZoneNames/en/Turkey/3=Turkey Summer Time TimeZoneNames/en/Turkey/4=TRST + +# bug 8255086 +LocaleNames//bn=Bangla +LocaleNames//fy=Western Frisian +LocaleNames//gl=Galician +LocaleNames//ht=Haitian Creole +LocaleNames//kj=Kuanyama +LocaleNames//kl=Kalaallisut +LocaleNames//ky=Kyrgyz +LocaleNames//nb=Norwegian Bokm\u00E5l +LocaleNames//or=Odia +LocaleNames//os=Ossetic +LocaleNames//pa=Punjabi +LocaleNames//ps=Pashto +LocaleNames//rm=Romansh +LocaleNames//si=Sinhala +LocaleNames//to=Tongan +LocaleNames//ug=Uyghur +LocaleNames//vo=Volap\u00FCk +LocaleNames//ang=Old English +LocaleNames//arc=Aramaic +LocaleNames//arn=Mapuche +LocaleNames//bas=Basaa +LocaleNames//car=Carib +LocaleNames//chn=Chinook Jargon +LocaleNames//crh=Crimean Turkish +LocaleNames//den=Slave +LocaleNames//dum=Middle Dutch +LocaleNames//egy=Ancient Egyptian +LocaleNames//enm=Middle English +LocaleNames//frm=Middle French +LocaleNames//fro=Old French +LocaleNames//gmh=Middle High German +LocaleNames//goh=Old High German +LocaleNames//grc=Ancient Greek +LocaleNames//gwi=Gwich\u02BCin +LocaleNames//luo=Luo +LocaleNames//lus=Mizo +LocaleNames//mga=Middle Irish +LocaleNames//mul=Multiple languages +LocaleNames//mus=Muscogee +LocaleNames//new=Newari +LocaleNames//nob=Bokm\u00E5l, Norwegian +LocaleNames//non=Old Norse +LocaleNames//nqo=N\u2019Ko +LocaleNames//nso=Northern Sotho +LocaleNames//ota=Ottoman Turkish +LocaleNames//peo=Old Persian +LocaleNames//pro=Old Proven\u00E7al +LocaleNames//sah=Sakha +LocaleNames//sga=Old Irish +LocaleNames//sog=Sogdien +LocaleNames//tog=Nyasa Tonga +LocaleNames//und=Unknown language +LocaleNames//vol=Volap\u00FCk +LocaleNames//wal=Wolaytta +LocaleNames//Beng=Bangla +LocaleNames//Geok=Georgian Khutsuri +LocaleNames//Hans=Simplified +LocaleNames//Hant=Traditional +LocaleNames//Hrkt=Japanese syllabaries +LocaleNames//Lana=Lanna +LocaleNames//Lisu=Fraser +LocaleNames//Mand=Mandaean +LocaleNames//Nkgb=Naxi Geba +LocaleNames//Orya=Odia +LocaleNames//Plrd=Pollard Phonetic +LocaleNames//Sind=Khudawadi +LocaleNames//Wara=Varang Kshiti +LocaleNames//Zinh=Inherited +LocaleNames//Zyyy=Common +LocaleNames//Zzzz=Unknown Script +LocaleNames//AG=Antigua & Barbuda +LocaleNames//AX=\u00C5land Islands +LocaleNames//BA=Bosnia & Herzegovina +LocaleNames//BL=St. Barth\u00E9lemy +LocaleNames//BQ=Caribbean Netherlands +LocaleNames//CC=Cocos (Keeling) Islands +LocaleNames//CD=Congo - Kinshasa +LocaleNames//CG=Congo - Brazzaville +LocaleNames//CI=C\u00F4te d\u2019Ivoire +LocaleNames//CW=Cura\u00E7ao +LocaleNames//CZ=Czechia +LocaleNames//GS=South Georgia & South Sandwich Islands +LocaleNames//HK=Hong Kong SAR China +LocaleNames//HM=Heard & McDonald Islands +LocaleNames//IM=Isle of Man +LocaleNames//KN=St. Kitts & Nevis +LocaleNames//LC=St. Lucia +LocaleNames//MF=St. Martin +LocaleNames//MK=North Macedonia +LocaleNames//MM=Myanmar (Burma) +LocaleNames//MO=Macao SAR China +LocaleNames//PM=St. Pierre & Miquelon +LocaleNames//PN=Pitcairn Islands +LocaleNames//PS=Palestinian Territories +LocaleNames//RE=R\u00E9union +LocaleNames//SH=St. Helena +LocaleNames//SJ=Svalbard & Jan Mayen +LocaleNames//ST=S\u00E3o Tom\u00E9 & Pr\u00EDncipe +LocaleNames//SX=Sint Maarten +LocaleNames//SZ=Eswatini +LocaleNames//TC=Turks & Caicos Islands +LocaleNames//TT=Trinidad & Tobago +LocaleNames//UM=U.S. Outlying Islands +LocaleNames//VA=Vatican City +LocaleNames//VC=St. Vincent & Grenadines +LocaleNames//WF=Wallis & Futuna +LocaleNames//035=Southeast Asia +LocaleNames//053=Australasia +LocaleNames//419=Latin America diff --git a/test/jdk/sun/text/resources/LocaleDataTest.java b/test/jdk/sun/text/resources/LocaleDataTest.java index 8cb88df3097..a686d3a4bbd 100644 --- a/test/jdk/sun/text/resources/LocaleDataTest.java +++ b/test/jdk/sun/text/resources/LocaleDataTest.java @@ -39,7 +39,7 @@ * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8134916 * 8145136 8145952 8164784 8037111 8081643 7037368 8178872 8185841 8190918 * 8187946 8195478 8181157 8179071 8193552 8202026 8204269 8202537 8208746 - * 8209775 8221432 8227127 8230284 8231273 8233579 8234288 8250665 + * 8209775 8221432 8227127 8230284 8231273 8233579 8234288 8250665 8255086 * @summary Verify locale data * @modules java.base/sun.util.resources * @modules jdk.localedata @@ -113,7 +113,7 @@ * FormatData/sr-Latn-BA/DayNames/2=utorak * * The command-line syntax of this test is - * java LocaleDataTest [-w] [{ -s | }] [-cldr] + * java --add-exports java.base/sun.util.resources=ALL-UNNAMED LocaleDataTest.java [-w] [{ -s | }] [-cldr] * * This program always sends its results to standard output. If -w is not specified, * this program prints out only the differences between the data file and the actual diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 1c58ec654cb..7dae9191b01 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -118,6 +118,7 @@ public Map call() { map.put("vm.musl", this::isMusl); map.put("release.implementor", this::implementor); map.put("test.vm.gc.nvdimm", this::isNvdimmTestEnabled); + map.put("jdk.containerized", this::jdkContainerized); vmGC(map); // vm.gc.X = true/false vmOptFinalFlags(map); @@ -545,6 +546,11 @@ private String isNvdimmTestEnabled() { return "" + "true".equalsIgnoreCase(isEnabled); } + private String jdkContainerized() { + String isEnabled = System.getenv("TEST_JDK_CONTAINERIZED"); + return "" + "true".equalsIgnoreCase(isEnabled); + } + /** * Dumps the map to the file if the file name is given as the property. * This functionality could be helpful to know context in the real diff --git a/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java b/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java index 706ec613f04..d35298134b9 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java @@ -23,12 +23,11 @@ /* * @test - * @bug 8236539 + * @bug 8236539 8246774 * @summary Relative link tags in record javadoc don't resolve * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox javadoc.tester.* - * @compile TestRecordLinks.java * @run main TestRecordLinks */ @@ -74,7 +73,6 @@ public void bar() { } javadoc("-d", base.resolve("out").toString(), "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "example"); checkExit(Exit.OK); diff --git a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java index 830bee551d7..2390eb8b383 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java @@ -23,13 +23,12 @@ /* * @test - * @bug 8225055 8239804 + * @bug 8225055 8239804 8246774 * @summary Record types * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox javadoc.tester.* - * @compile --enable-preview --source ${jdk.version} TestRecordTypes.java - * @run main/othervm --enable-preview TestRecordTypes + * @run main TestRecordTypes */ @@ -69,7 +68,6 @@ public void testRecordKeywordUnnamedPackage(Path base) throws IOException { javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, src.resolve("R.java").toString()); checkExit(Exit.OK); @@ -91,7 +89,6 @@ public void testRecordKeywordNamedPackage(Path base) throws IOException { javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -113,7 +110,6 @@ public void testEmptyRecord(Path base) throws IOException { javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -139,7 +135,6 @@ public record R(int r1) { }"""); javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -171,7 +166,6 @@ public record R(int r1) { }"""); javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -204,7 +198,6 @@ public record R(int r1) { }"""); javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -268,7 +261,6 @@ public record R(int r1) { }"""); "-quiet", "-noindex", "-sourcepath", src.toString(), "-linkoffline", externalDocs, localDocs, - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -349,7 +341,6 @@ public record R(""" + comps + ") { }"); "-quiet", "-noindex", "--no-platform-links", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -375,7 +366,6 @@ public record R(int r1) { javadoc("-d", base.resolve("out").toString(), "-quiet", "-noindex", "-sourcepath", src.toString(), - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); @@ -406,7 +396,6 @@ public void testExamples(Path base) throws IOException { "-quiet", "-noindex", "-sourcepath", testSrc.toString(), "-linksource", - "--enable-preview", "--source", thisRelease, "examples"); checkExit(Exit.OK); @@ -415,13 +404,11 @@ public void testExamples(Path base) throws IOException { "-sourcepath", testSrc.toString(), "-linksource", "-linkoffline", externalDocs, localDocs, - "--enable-preview", "--source", thisRelease, "examples"); checkExit(Exit.OK); } @Test - @SuppressWarnings("preview") public void testAnnotations(Path base) throws IOException { ElementType[] types = { ElementType.FIELD, @@ -468,7 +455,6 @@ void testAnnotations(Path base, Set types) throws IOException { "--no-platform-links", "-sourcepath", src.toString(), "-private", - "--enable-preview", "--source", thisRelease, "p"); checkExit(Exit.OK); diff --git a/test/langtools/jdk/javadoc/tool/api/basic/GetTask_DiagListenerTest.java b/test/langtools/jdk/javadoc/tool/api/basic/GetTask_DiagListenerTest.java index bbead5a206f..8e51bdbc50e 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/GetTask_DiagListenerTest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/GetTask_DiagListenerTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6493690 + * @bug 6493690 8246774 * @summary javadoc should have a javax.tools.Tool service provider * @modules java.compiler * jdk.compiler @@ -78,7 +78,7 @@ public void testDiagListener() throws Exception { } List expect = Arrays.asList( "javadoc.note.msg", // Loading source file - "compiler.err.expected3", // class, interface, enum, or __datum expected + "compiler.err.expected4", // class, interface, enum, or record expected "javadoc.note.msg"); // 1 error if (!diagCodes.equals(expect)) throw new Exception("unexpected diagnostics occurred"); diff --git a/test/langtools/jdk/jshell/CompletenessTest.java b/test/langtools/jdk/jshell/CompletenessTest.java index 6ff4ce4d55a..97e165abb7a 100644 --- a/test/langtools/jdk/jshell/CompletenessTest.java +++ b/test/langtools/jdk/jshell/CompletenessTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8149524 8131024 8165211 8080071 8130454 8167343 8129559 8114842 8182268 8223782 8235474 + * @bug 8149524 8131024 8165211 8080071 8130454 8167343 8129559 8114842 8182268 8223782 8235474 8246774 * @summary Test SourceCodeAnalysis * @build KullaTesting TestingInputStream * @run testng CompletenessTest @@ -379,10 +379,4 @@ public void testMiscSource() { assertStatus("int[] m = {1, 2}, n = new int[0]; int i;", COMPLETE, "int[] m = {1, 2}, n = new int[0];"); } - - @BeforeMethod - public void setUp() { - setUp(b -> b.compilerOptions("--enable-preview", "-source", String.valueOf(SourceVersion.latest().ordinal()))); - } - } diff --git a/test/langtools/jdk/jshell/RecordsTest.java b/test/langtools/jdk/jshell/RecordsTest.java index bdca879edde..69aaae8e46f 100644 --- a/test/langtools/jdk/jshell/RecordsTest.java +++ b/test/langtools/jdk/jshell/RecordsTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8235474 8236715 + * @bug 8235474 8236715 8246774 * @summary Tests for evalution of records * @modules jdk.jshell * @build KullaTesting TestingInputStream ExpectedDiagnostic @@ -76,10 +76,4 @@ public void testRecordMethod() { assertEval("record(\"r\")", "\"rr\""); assertEval("record(\"r\").length()", "2"); } - - @BeforeMethod - public void setUp() { - setUp(b -> b.compilerOptions("--enable-preview", "-source", String.valueOf(SourceVersion.latest().ordinal())) - .remoteVMOptions("--enable-preview")); - } } diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java index 6f38ad6fc0e..6a50d9bc9f1 100644 --- a/test/langtools/jdk/jshell/ToolSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolSimpleTest.java @@ -23,14 +23,14 @@ /* * @test - * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 8239536 8247456 + * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 8239536 8247456 8246774 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap * jdk.jshell/jdk.internal.jshell.tool * @build KullaTesting TestingInputStream - * @run testng/othervm ToolSimpleTest + * @run testng ToolSimpleTest */ import java.util.ArrayList; @@ -917,7 +917,7 @@ public void testUpdateFalsePositive() { @Test public void testRecords() { - test(new String[] {"--enable-preview"}, + test(new String[] {}, (a) -> assertCommandOutputContains(a, "record R(int i) { public int g() { return j; } }", "| created record R, however, it cannot be instantiated or its methods invoked until variable j is declared"), (a) -> assertCommandOutputContains(a, "new R(0)", diff --git a/test/langtools/tools/javac/IllegalAnnotation.java b/test/langtools/tools/javac/IllegalAnnotation.java index 164d1786146..79c4194d0c5 100644 --- a/test/langtools/tools/javac/IllegalAnnotation.java +++ b/test/langtools/tools/javac/IllegalAnnotation.java @@ -1,10 +1,9 @@ /** * @test /nodynamiccopyright/ - * @bug 5012028 6384539 8074364 8250741 + * @bug 5012028 6384539 8074364 8250741 8246774 * @summary javac crash when declare an annotation type illegally * * @compile/fail/ref=IllegalAnnotation.out -XDrawDiagnostics IllegalAnnotation.java - * @compile/fail/ref=IllegalAnnotation.out -XDrawDiagnostics --enable-preview -source ${jdk.version} IllegalAnnotation.java */ class IllegalAnnotation { { diff --git a/test/langtools/tools/javac/IllegalAnnotation.out b/test/langtools/tools/javac/IllegalAnnotation.out index 6b99a40d084..00d7fd4e2a3 100644 --- a/test/langtools/tools/javac/IllegalAnnotation.out +++ b/test/langtools/tools/javac/IllegalAnnotation.out @@ -1,2 +1,2 @@ -IllegalAnnotation.java:11:10: compiler.err.annotation.decl.not.allowed.here +IllegalAnnotation.java:10:10: compiler.err.annotation.decl.not.allowed.here 1 error diff --git a/test/langtools/tools/javac/LocalInterface.java b/test/langtools/tools/javac/LocalInterface.java index 13c2d56bdf1..818bb69ceab 100644 --- a/test/langtools/tools/javac/LocalInterface.java +++ b/test/langtools/tools/javac/LocalInterface.java @@ -1,9 +1,9 @@ /** * @test /nodynamiccopyright/ - * @bug 8242478 + * @bug 8242478 8246774 * @summary test for local interfaces - * @compile/fail/ref=LocalInterface.out -XDrawDiagnostics LocalInterface.java - * @compile --enable-preview -source ${jdk.version} LocalInterface.java + * @compile/fail/ref=LocalInterface.out -XDrawDiagnostics -source 15 LocalInterface.java + * @compile LocalInterface.java */ class LocalInterface { void m() { diff --git a/test/langtools/tools/javac/LocalInterface.out b/test/langtools/tools/javac/LocalInterface.out index 2ad6d4011d9..98524edadc0 100644 --- a/test/langtools/tools/javac/LocalInterface.out +++ b/test/langtools/tools/javac/LocalInterface.out @@ -1,2 +1,4 @@ +- compiler.warn.source.no.system.modules.path: 15 LocalInterface.java:10:9: compiler.err.intf.not.allowed.here 1 error +1 warning diff --git a/test/langtools/tools/javac/LocalRecord.java b/test/langtools/tools/javac/LocalRecord.java index 9dda54e04d6..b4053bb1fe3 100644 --- a/test/langtools/tools/javac/LocalRecord.java +++ b/test/langtools/tools/javac/LocalRecord.java @@ -23,9 +23,9 @@ /* * @test - * @bug 8242478 + * @bug 8242478 8246774 * @summary test local records - * @compile --enable-preview -source ${jdk.version} LocalRecord.java + * @compile LocalRecord.java */ class LocalRecord { void m() { diff --git a/test/langtools/tools/javac/annotations/ApplicableAnnotationsOnRecords.java b/test/langtools/tools/javac/annotations/ApplicableAnnotationsOnRecords.java index 05845700903..da5c6746047 100644 --- a/test/langtools/tools/javac/annotations/ApplicableAnnotationsOnRecords.java +++ b/test/langtools/tools/javac/annotations/ApplicableAnnotationsOnRecords.java @@ -24,12 +24,11 @@ /* * @test * @summary test for com.sun.tools.javac.comp.Check::validateAnnotation, com.sun.tools.javac.code.SymbolMetadata::removeDeclarationMetadata and ::removeFromCompoundList - * @bug 8241312 + * @bug 8241312 8246774 * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.util * jdk.jdeps/com.sun.tools.classfile - * @compile --enable-preview -source ${jdk.version} ApplicableAnnotationsOnRecords.java - * @run main/othervm --enable-preview ApplicableAnnotationsOnRecords + * @run main ApplicableAnnotationsOnRecords */ import com.sun.tools.classfile.*; import com.sun.tools.javac.util.Assert; diff --git a/test/langtools/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java b/test/langtools/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java index b22b3d10638..bf03407f754 100644 --- a/test/langtools/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java +++ b/test/langtools/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7151010 8006547 8007766 8029017 + * @bug 7151010 8006547 8007766 8029017 8246774 * @summary Default test cases for running combinations for Target values * @modules jdk.compiler * @build Helper @@ -204,25 +204,22 @@ public static void main(String args[]) throws Exception { } } - // options to be passed if all targets, including RECORD_COMPONENTS, are to be considered - List previewOptions = List.of( - "--enable-preview", - "-source", Integer.toString(Runtime.version().feature()) - ); + // options to be passed if target RECORD_COMPONENT can't be considered + List source8 = List.of("-source", "8"); private void generate() { // Adding test cases to run. testCases.addAll(Arrays.asList( // No base target against no container target. - new TestCase(noSet, noSet), + /* 0*/ new TestCase(noSet, noSet), // No base target against empty container target. - new TestCase(noSet, empty), + /* 1*/ new TestCase(noSet, empty), // No base target against TYPE_USE only container target. - new TestCase(noSet, less(jdk8, TYPE_PARAMETER)), + new TestCase(noSet, less(jdk8, TYPE_PARAMETER), source8), // No base target against TYPE_PARAMETER only container target. - new TestCase(noSet, less(jdk8, TYPE_USE)), + new TestCase(noSet, less(jdk8, TYPE_USE), source8), // No base target against TYPE_USE + TYPE_PARAMETER only container target. - new TestCase(noSet, jdk8), + new TestCase(noSet, jdk8, source8), // No base target against TYPE_USE + some selection of jdk7 targets. new TestCase(noSet, plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_USE)), @@ -233,7 +230,7 @@ private void generate() { new TestCase(noSet, plus(empty, TYPE)), new TestCase(noSet, plus(empty, PARAMETER)), new TestCase(noSet, plus(empty, PACKAGE)), - new TestCase(noSet, plus(empty, METHOD)), + /* 10*/ new TestCase(noSet, plus(empty, METHOD)), new TestCase(noSet, plus(empty, LOCAL_VARIABLE)), new TestCase(noSet, plus(empty, FIELD)), new TestCase(noSet, plus(empty, CONSTRUCTOR)), @@ -246,32 +243,32 @@ private void generate() { new TestCase(empty, plus(empty, TYPE)), new TestCase(empty, plus(empty, PARAMETER)), new TestCase(empty, plus(empty, PACKAGE)), - new TestCase(empty, plus(empty, METHOD)), + /* 20*/ new TestCase(empty, plus(empty, METHOD)), new TestCase(empty, plus(empty, LOCAL_VARIABLE)), new TestCase(empty, plus(empty, FIELD)), new TestCase(empty, plus(empty, CONSTRUCTOR)), new TestCase(empty, plus(empty, ANNOTATION_TYPE)), - new TestCase(empty, less(jdk8, TYPE_USE)), - new TestCase(empty, less(jdk8, TYPE_PARAMETER)), + new TestCase(empty, less(jdk8, TYPE_USE), source8), + new TestCase(empty, less(jdk8, TYPE_PARAMETER), source8), // No container target against all all-but one jdk7 targets. - new TestCase(less(jdk7, TYPE), noSet), - new TestCase(less(jdk7, PARAMETER), noSet), - new TestCase(less(jdk7, PACKAGE), noSet), - new TestCase(less(jdk7, METHOD), noSet), - new TestCase(less(jdk7, LOCAL_VARIABLE), noSet), - new TestCase(less(jdk7, FIELD), noSet), - new TestCase(less(jdk7, CONSTRUCTOR), noSet), - new TestCase(less(jdk7, ANNOTATION_TYPE), noSet), + new TestCase(less(jdk7, TYPE), noSet, source8), + new TestCase(less(jdk7, PARAMETER), noSet, source8), + new TestCase(less(jdk7, PACKAGE), noSet, source8), + /* 30*/ new TestCase(less(jdk7, METHOD), noSet, source8), + new TestCase(less(jdk7, LOCAL_VARIABLE), noSet, source8), + new TestCase(less(jdk7, FIELD), noSet, source8), + new TestCase(less(jdk7, CONSTRUCTOR), noSet, source8), + new TestCase(less(jdk7, ANNOTATION_TYPE), noSet, source8), // No container against all but TYPE and ANNOTATION_TYPE new TestCase(less(jdk7, TYPE, ANNOTATION_TYPE), noSet), // No container against jdk7 targets. - new TestCase(jdk7, noSet), + new TestCase(jdk7, noSet, source8), // No container against jdk7 targets plus one or both of TYPE_USE, TYPE_PARAMETER - new TestCase(plus(jdk7, TYPE_USE), noSet), - new TestCase(plus(jdk7, TYPE_PARAMETER), noSet), - new TestCase(allTargets, noSet, previewOptions), + new TestCase(plus(jdk7, TYPE_USE), noSet, source8), + new TestCase(plus(jdk7, TYPE_PARAMETER), noSet, source8), + new TestCase(allTargets, noSet, null), // Empty container target against any lone target. - new TestCase(plus(empty, TYPE), empty), + /* 40*/ new TestCase(plus(empty, TYPE), empty), new TestCase(plus(empty, PARAMETER), empty), new TestCase(plus(empty, PACKAGE), empty), new TestCase(plus(empty, METHOD), empty), @@ -282,34 +279,34 @@ private void generate() { new TestCase(plus(empty, TYPE_USE), empty), new TestCase(plus(empty, TYPE_PARAMETER), empty), // All base targets against all container targets. - new TestCase(allTargets, allTargets, previewOptions), + /* 50*/ new TestCase(allTargets, allTargets), // All base targets against all but one container targets. - new TestCase(allTargets, less(allTargets, TYPE), previewOptions), - new TestCase(allTargets, less(allTargets, PARAMETER), previewOptions), - new TestCase(allTargets, less(allTargets, PACKAGE), previewOptions), - new TestCase(allTargets, less(allTargets, METHOD), previewOptions), - new TestCase(allTargets, less(allTargets, LOCAL_VARIABLE), previewOptions), - new TestCase(allTargets, less(allTargets, FIELD), previewOptions), - new TestCase(allTargets, less(allTargets, CONSTRUCTOR), previewOptions), - new TestCase(allTargets, less(allTargets, ANNOTATION_TYPE), previewOptions), - new TestCase(allTargets, less(allTargets, TYPE_USE), previewOptions), - new TestCase(allTargets, less(allTargets, TYPE_PARAMETER), previewOptions), + new TestCase(allTargets, less(allTargets, TYPE)), + new TestCase(allTargets, less(allTargets, PARAMETER)), + new TestCase(allTargets, less(allTargets, PACKAGE)), + new TestCase(allTargets, less(allTargets, METHOD)), + new TestCase(allTargets, less(allTargets, LOCAL_VARIABLE)), + new TestCase(allTargets, less(allTargets, FIELD)), + new TestCase(allTargets, less(allTargets, CONSTRUCTOR)), + new TestCase(allTargets, less(allTargets, ANNOTATION_TYPE)), + new TestCase(allTargets, less(allTargets, TYPE_USE)), + /* 60*/ new TestCase(allTargets, less(allTargets, TYPE_PARAMETER)), // All container targets against all but one base targets. - new TestCase(less(allTargets, TYPE), allTargets, previewOptions), - new TestCase(less(allTargets, PARAMETER), allTargets, previewOptions), - new TestCase(less(allTargets, PACKAGE), allTargets, previewOptions), - new TestCase(less(allTargets, METHOD), allTargets, previewOptions), - new TestCase(less(allTargets, LOCAL_VARIABLE), allTargets, previewOptions), - new TestCase(less(allTargets, FIELD), allTargets, previewOptions), - new TestCase(less(allTargets, CONSTRUCTOR), allTargets, previewOptions), - new TestCase(less(allTargets, ANNOTATION_TYPE), allTargets, previewOptions), - new TestCase(less(allTargets, TYPE_USE), allTargets, previewOptions), - new TestCase(less(allTargets, TYPE_PARAMETER), allTargets, previewOptions))); + new TestCase(less(allTargets, TYPE), allTargets), + new TestCase(less(allTargets, PARAMETER), allTargets), + new TestCase(less(allTargets, PACKAGE), allTargets), + new TestCase(less(allTargets, METHOD), allTargets), + new TestCase(less(allTargets, LOCAL_VARIABLE), allTargets), + new TestCase(less(allTargets, FIELD), allTargets), + new TestCase(less(allTargets, CONSTRUCTOR), allTargets), + new TestCase(less(allTargets, ANNOTATION_TYPE), allTargets), + new TestCase(less(allTargets, TYPE_USE), allTargets), + /* 70*/ new TestCase(less(allTargets, TYPE_PARAMETER), allTargets))); // Generates 100 test cases for any lone base target contained in Set // allTargets against any lone container target. for (ElementType b : allTargets) { for (ElementType c : allTargets) { - testCases.add(new TestCase(plus(empty, b), plus(empty, c), previewOptions)); + testCases.add(new TestCase(plus(empty, b), plus(empty, c))); } } } @@ -456,7 +453,7 @@ private boolean getCompileResult(String className, boolean shouldCompile, if (allDiagnostics.stream().noneMatch(d -> d.getKind() == javax.tools.Diagnostic.Kind.ERROR)) { ok = true; } else { - errMesg = "Test failed, compiled unexpectedly."; + errMesg = "Test failed, should have compiled successfully."; ok = false; } } else { diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsPositionsOnRecords.java b/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsPositionsOnRecords.java index 17b94730e54..551bd981c21 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsPositionsOnRecords.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsPositionsOnRecords.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8246774 * @summary Verify location of type annotations on records * @library /tools/lib * @modules @@ -32,8 +33,7 @@ * jdk.compiler/com.sun.tools.javac.code * jdk.compiler/com.sun.tools.javac.util * @build toolbox.ToolBox toolbox.JavacTask - * @compile --enable-preview -source ${jdk.version} TypeAnnotationsPositionsOnRecords.java - * @run main/othervm --enable-preview TypeAnnotationsPositionsOnRecords + * @run main TypeAnnotationsPositionsOnRecords */ import java.util.List; @@ -105,7 +105,6 @@ void run() throws Exception { void compileTestClass() throws Exception { new JavacTask(tb) .sources(src) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature())) .run(); } diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out index 91589d9252e..301f7335520 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out @@ -1,7 +1,7 @@ AnnotatedImport.java:10:13: compiler.err.expected: token.identifier -AnnotatedImport.java:10:16: compiler.err.expected3: class, interface, enum +AnnotatedImport.java:10:16: compiler.err.expected4: class, interface, enum, record AnnotatedImport.java:11:7: compiler.err.expected: token.identifier -AnnotatedImport.java:11:11: compiler.err.expected3: class, interface, enum +AnnotatedImport.java:11:11: compiler.err.expected4: class, interface, enum, record AnnotatedImport.java:12:18: compiler.err.expected: token.identifier -AnnotatedImport.java:12:21: compiler.err.expected3: class, interface, enum +AnnotatedImport.java:12:21: compiler.err.expected4: class, interface, enum, record 6 errors diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out index b2c1770b3b5..cb2e66ca6db 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out @@ -1,3 +1,3 @@ AnnotatedPackage1.java:9:14: compiler.err.expected: token.identifier -AnnotatedPackage1.java:9:17: compiler.err.expected3: class, interface, enum +AnnotatedPackage1.java:9:17: compiler.err.expected4: class, interface, enum, record 2 errors diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out index 77b25afc5e0..c511caf6546 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out @@ -1,3 +1,3 @@ AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier -AnnotatedPackage2.java:9:12: compiler.err.expected3: class, interface, enum +AnnotatedPackage2.java:9:12: compiler.err.expected4: class, interface, enum, record 2 errors diff --git a/test/langtools/tools/javac/api/TestGetScopeResult.java b/test/langtools/tools/javac/api/TestGetScopeResult.java index b2a2e500e03..60913ac0050 100644 --- a/test/langtools/tools/javac/api/TestGetScopeResult.java +++ b/test/langtools/tools/javac/api/TestGetScopeResult.java @@ -23,13 +23,12 @@ /* * @test - * @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 8240658 + * @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 8240658 8246774 * @summary Test the outcomes from Trees.getScope * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.comp * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @compile TestGetScopeResult.java */ import java.io.IOException; @@ -559,9 +558,7 @@ public String getCharContent(boolean ignoreEncodingErrors) { } Context ctx = new Context(); TestAnalyzer.preRegister(ctx); - List options = List.of("--enable-preview", - "-source", System.getProperty("java.specification.version")); - JavacTask t = (JavacTask) c.getTask(null, fm, null, options, null, + JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null, List.of(new MyFileObject()), ctx); CompilationUnitTree cut = t.parse().iterator().next(); t.analyze(); @@ -636,9 +633,7 @@ public String getCharContent(boolean ignoreEncodingErrors) { } Context ctx = new Context(); TestAnalyzer.preRegister(ctx); - List options = List.of("--enable-preview", - "-source", System.getProperty("java.specification.version")); - JavacTask t = (JavacTask) c.getTask(null, fm, null, options, null, + JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null, List.of(new MyFileObject()), ctx); CompilationUnitTree cut = t.parse().iterator().next(); t.analyze(); diff --git a/test/langtools/tools/javac/diags/examples/AccessorCantBeGeneric.java b/test/langtools/tools/javac/diags/examples/AccessorCantBeGeneric.java index 9594b5a561a..8027475b90b 100644 --- a/test/langtools/tools/javac/diags/examples/AccessorCantBeGeneric.java +++ b/test/langtools/tools/javac/diags/examples/AccessorCantBeGeneric.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,6 @@ // key: compiler.err.invalid.accessor.method.in.record // key: compiler.misc.accessor.method.must.not.be.generic -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int i) { public int i() { diff --git a/test/langtools/tools/javac/diags/examples/AccessorCantThrowException.java b/test/langtools/tools/javac/diags/examples/AccessorCantThrowException.java index f4dcbf305a7..47e2566348e 100644 --- a/test/langtools/tools/javac/diags/examples/AccessorCantThrowException.java +++ b/test/langtools/tools/javac/diags/examples/AccessorCantThrowException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,6 @@ // key: compiler.err.invalid.accessor.method.in.record // key: compiler.misc.accessor.method.cant.throw.exception -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int i) { public int i() throws ArithmeticException { diff --git a/test/langtools/tools/javac/diags/examples/AccessorMethodCantBeStatic.java b/test/langtools/tools/javac/diags/examples/AccessorMethodCantBeStatic.java index 7299c746207..868a4dd1821 100644 --- a/test/langtools/tools/javac/diags/examples/AccessorMethodCantBeStatic.java +++ b/test/langtools/tools/javac/diags/examples/AccessorMethodCantBeStatic.java @@ -23,9 +23,6 @@ // key: compiler.err.invalid.accessor.method.in.record // key: compiler.misc.accessor.method.must.not.be.static -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int x) { static final int j = 0; diff --git a/test/langtools/tools/javac/diags/examples/AccessorReturnTypeDoesntMatch.java b/test/langtools/tools/javac/diags/examples/AccessorReturnTypeDoesntMatch.java index b8af12cc6f9..a11c79b9161 100644 --- a/test/langtools/tools/javac/diags/examples/AccessorReturnTypeDoesntMatch.java +++ b/test/langtools/tools/javac/diags/examples/AccessorReturnTypeDoesntMatch.java @@ -23,9 +23,6 @@ // key: compiler.err.invalid.accessor.method.in.record // key: compiler.misc.accessor.return.type.doesnt.match -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} import java.util.List; record R(List x) { diff --git a/test/langtools/tools/javac/diags/examples/CanonicalCantHaveStrongerAccessPrivileges.java b/test/langtools/tools/javac/diags/examples/CanonicalCantHaveStrongerAccessPrivileges.java index 7364e698543..2104d3a9287 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalCantHaveStrongerAccessPrivileges.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalCantHaveStrongerAccessPrivileges.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.canonical.must.not.have.stronger.access -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} public record CanonicalCantHaveStrongerAccessPrivileges() { private CanonicalCantHaveStrongerAccessPrivileges {} diff --git a/test/langtools/tools/javac/diags/examples/CanonicalCantInvokeOtherConstructor.java b/test/langtools/tools/javac/diags/examples/CanonicalCantInvokeOtherConstructor.java index 89dc304bcfc..1c62e2ede88 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalCantInvokeOtherConstructor.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalCantInvokeOtherConstructor.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.canonical.must.not.contain.explicit.constructor.invocation -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} record R(int x) { public R(int x) { super(); this.x = x; } diff --git a/test/langtools/tools/javac/diags/examples/CanonicalConstructorArgumentMismatch.java b/test/langtools/tools/javac/diags/examples/CanonicalConstructorArgumentMismatch.java index 91d7fcb9881..621d26dbdd6 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalConstructorArgumentMismatch.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalConstructorArgumentMismatch.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.canonical.with.name.mismatch -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} record R(int x) { public R(int _x) { this.x = _x; } diff --git a/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveReturn.java b/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveReturn.java index 0033ac8761d..6f86a867bd7 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveReturn.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveReturn.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.canonical.cant.have.return.statement -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.compact -// options: --enable-preview -source ${jdk.version} record R() { public R { diff --git a/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveThrowsClause.java b/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveThrowsClause.java index 6c3e165ead9..26003a3a1a7 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveThrowsClause.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalConstructorCantHaveThrowsClause.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.throws.clause.not.allowed.for.canonical.constructor -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} record R(int i) { public R(int i) throws Exception { diff --git a/test/langtools/tools/javac/diags/examples/CanonicalMustNotDeclareTypeVariables.java b/test/langtools/tools/javac/diags/examples/CanonicalMustNotDeclareTypeVariables.java index 5ab9185a7ed..1060955d102 100644 --- a/test/langtools/tools/javac/diags/examples/CanonicalMustNotDeclareTypeVariables.java +++ b/test/langtools/tools/javac/diags/examples/CanonicalMustNotDeclareTypeVariables.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.canonical.must.not.declare.type.variables -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} record R(int i) { public R(int i) { diff --git a/test/langtools/tools/javac/diags/examples/ConstructorWithSameErasureAsCanonical.java b/test/langtools/tools/javac/diags/examples/ConstructorWithSameErasureAsCanonical.java index dcccae65d66..28d485c48ef 100644 --- a/test/langtools/tools/javac/diags/examples/ConstructorWithSameErasureAsCanonical.java +++ b/test/langtools/tools/javac/diags/examples/ConstructorWithSameErasureAsCanonical.java @@ -23,10 +23,7 @@ // key: compiler.err.invalid.canonical.constructor.in.record // key: compiler.misc.type.must.be.identical.to.corresponding.record.component.type -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile // key: compiler.misc.canonical -// options: --enable-preview -source ${jdk.version} import java.util.List; diff --git a/test/langtools/tools/javac/diags/examples/Expected3.java b/test/langtools/tools/javac/diags/examples/Expected3.java index 72fd7d7c43c..2b1ec325618 100644 --- a/test/langtools/tools/javac/diags/examples/Expected3.java +++ b/test/langtools/tools/javac/diags/examples/Expected3.java @@ -22,5 +22,7 @@ */ // key: compiler.err.expected3 +// key: compiler.warn.source.no.system.modules.path +// options: -source 15 int Expected3; diff --git a/test/langtools/tools/javac/diags/examples/FirstInvocationMustBeAnotherConstructor.java b/test/langtools/tools/javac/diags/examples/FirstInvocationMustBeAnotherConstructor.java index 2fdb1c4f5ae..e2478244cc9 100644 --- a/test/langtools/tools/javac/diags/examples/FirstInvocationMustBeAnotherConstructor.java +++ b/test/langtools/tools/javac/diags/examples/FirstInvocationMustBeAnotherConstructor.java @@ -22,9 +22,6 @@ */ // key: compiler.err.first.statement.must.be.call.to.another.constructor -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int x) { public R(int x, int y) { this.x = x; } diff --git a/test/langtools/tools/javac/diags/examples/IllegalRecordComponentName.java b/test/langtools/tools/javac/diags/examples/IllegalRecordComponentName.java index 483ac93a7e7..45a7a153839 100644 --- a/test/langtools/tools/javac/diags/examples/IllegalRecordComponentName.java +++ b/test/langtools/tools/javac/diags/examples/IllegalRecordComponentName.java @@ -22,8 +22,5 @@ */ // key: compiler.err.illegal.record.component.name -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int hashCode) {} diff --git a/test/langtools/tools/javac/diags/examples/IncorrectRecordDeclaration.java b/test/langtools/tools/javac/diags/examples/IncorrectRecordDeclaration.java index acaecb37755..dc1dd8af632 100644 --- a/test/langtools/tools/javac/diags/examples/IncorrectRecordDeclaration.java +++ b/test/langtools/tools/javac/diags/examples/IncorrectRecordDeclaration.java @@ -22,8 +22,5 @@ */ // key: compiler.err.record.header.expected -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R {} diff --git a/test/langtools/tools/javac/diags/examples/InstanceInitializersNotAllowedInRecords.java b/test/langtools/tools/javac/diags/examples/InstanceInitializersNotAllowedInRecords.java index 6b57276d865..b12c26ba0a5 100644 --- a/test/langtools/tools/javac/diags/examples/InstanceInitializersNotAllowedInRecords.java +++ b/test/langtools/tools/javac/diags/examples/InstanceInitializersNotAllowedInRecords.java @@ -22,9 +22,6 @@ */ // key: compiler.err.instance.initializer.not.allowed.in.records -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int x) { {} diff --git a/test/langtools/tools/javac/diags/examples/InterfaceNotAllowed.java b/test/langtools/tools/javac/diags/examples/InterfaceNotAllowed.java index 3c3feb692d4..a72e7ef12bd 100644 --- a/test/langtools/tools/javac/diags/examples/InterfaceNotAllowed.java +++ b/test/langtools/tools/javac/diags/examples/InterfaceNotAllowed.java @@ -22,6 +22,8 @@ */ // key: compiler.err.intf.not.allowed.here +// key: compiler.warn.source.no.system.modules.path +// options: -source 15 class InterfaceNotAllowed { void m() { diff --git a/test/langtools/tools/javac/diags/examples/InvalidSuperTypeRecord.java b/test/langtools/tools/javac/diags/examples/InvalidSuperTypeRecord.java index 8e8b0599c13..d12665681bf 100644 --- a/test/langtools/tools/javac/diags/examples/InvalidSuperTypeRecord.java +++ b/test/langtools/tools/javac/diags/examples/InvalidSuperTypeRecord.java @@ -22,7 +22,6 @@ */ // key: compiler.err.invalid.supertype.record -// options: --enable-preview -source ${jdk.version} @SuppressWarnings("preview") class R extends Record {} diff --git a/test/langtools/tools/javac/diags/examples/KindnameRecord.java b/test/langtools/tools/javac/diags/examples/KindnameRecord.java index 3ee2450e9ed..056e43a0205 100644 --- a/test/langtools/tools/javac/diags/examples/KindnameRecord.java +++ b/test/langtools/tools/javac/diags/examples/KindnameRecord.java @@ -27,10 +27,6 @@ // key: compiler.misc.kindname.method // key: compiler.err.already.defined // key: compiler.err.error -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// key: compiler.note.note // run: backdoor -// options: --enable-preview -source ${jdk.version} record R(int i, int i) {} diff --git a/test/langtools/tools/javac/diags/examples/LocalEnum.java b/test/langtools/tools/javac/diags/examples/LocalEnum.java index 431d6d931e9..fdf875c9697 100644 --- a/test/langtools/tools/javac/diags/examples/LocalEnum.java +++ b/test/langtools/tools/javac/diags/examples/LocalEnum.java @@ -22,6 +22,8 @@ */ // key: compiler.err.local.enum +// key: compiler.warn.source.no.system.modules.path +// options: -source 15 class LocalEnum { void m() { diff --git a/test/langtools/tools/javac/diags/examples/MethodMustBePublic.java b/test/langtools/tools/javac/diags/examples/MethodMustBePublic.java index c104261d361..fb48b1d7578 100644 --- a/test/langtools/tools/javac/diags/examples/MethodMustBePublic.java +++ b/test/langtools/tools/javac/diags/examples/MethodMustBePublic.java @@ -23,9 +23,6 @@ // key: compiler.err.invalid.accessor.method.in.record // key: compiler.misc.method.must.be.public -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int x) { private int x() { return x; } diff --git a/test/langtools/tools/javac/diags/examples/Records.java b/test/langtools/tools/javac/diags/examples/Records.java index 65b2c380cd6..9acc44d0f43 100644 --- a/test/langtools/tools/javac/diags/examples/Records.java +++ b/test/langtools/tools/javac/diags/examples/Records.java @@ -22,7 +22,8 @@ */ // key: compiler.misc.feature.records -// key: compiler.warn.preview.feature.use.plural -// options: --enable-preview -source ${jdk.version} -Xlint:preview +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.warn.source.no.system.modules.path +// options: -source 15 record R() {} diff --git a/test/langtools/tools/javac/diags/examples/RecordsCanNotDeclareInstanceFields.java b/test/langtools/tools/javac/diags/examples/RecordsCanNotDeclareInstanceFields.java index 20f9ab1ccf0..d98bcae9911 100644 --- a/test/langtools/tools/javac/diags/examples/RecordsCanNotDeclareInstanceFields.java +++ b/test/langtools/tools/javac/diags/examples/RecordsCanNotDeclareInstanceFields.java @@ -22,9 +22,6 @@ */ // key: compiler.err.record.cannot.declare.instance.fields -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int i) { private final int y = 0; diff --git a/test/langtools/tools/javac/diags/examples/RecordsCantDeclareComponentModifiers.java b/test/langtools/tools/javac/diags/examples/RecordsCantDeclareComponentModifiers.java index 3fda0742cf4..2bf01b9e7a3 100644 --- a/test/langtools/tools/javac/diags/examples/RecordsCantDeclareComponentModifiers.java +++ b/test/langtools/tools/javac/diags/examples/RecordsCantDeclareComponentModifiers.java @@ -22,8 +22,5 @@ */ // key: compiler.err.record.cant.declare.field.modifiers -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(final int x) {} diff --git a/test/langtools/tools/javac/diags/examples/RecordsComponentsCanNotDeclareCStyleArrays.java b/test/langtools/tools/javac/diags/examples/RecordsComponentsCanNotDeclareCStyleArrays.java index 6d2d5186e24..dcc06349038 100644 --- a/test/langtools/tools/javac/diags/examples/RecordsComponentsCanNotDeclareCStyleArrays.java +++ b/test/langtools/tools/javac/diags/examples/RecordsComponentsCanNotDeclareCStyleArrays.java @@ -22,8 +22,5 @@ */ // key: compiler.err.record.component.and.old.array.syntax -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} record R(int i[]) {} diff --git a/test/langtools/tools/javac/diags/examples/RecordsNotAllowedInInnerClasses.java b/test/langtools/tools/javac/diags/examples/RecordsNotAllowedInInnerClasses.java index 99000219c42..1016a874e00 100644 --- a/test/langtools/tools/javac/diags/examples/RecordsNotAllowedInInnerClasses.java +++ b/test/langtools/tools/javac/diags/examples/RecordsNotAllowedInInnerClasses.java @@ -22,9 +22,6 @@ */ // key: compiler.err.static.declaration.not.allowed.in.inner.classes -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --enable-preview -source ${jdk.version} class Outer { class Inner { diff --git a/test/langtools/tools/javac/enum/FauxEnum3.java b/test/langtools/tools/javac/enum/FauxEnum3.java index 83bb06f80ee..ec53aeb5951 100644 --- a/test/langtools/tools/javac/enum/FauxEnum3.java +++ b/test/langtools/tools/javac/enum/FauxEnum3.java @@ -5,7 +5,6 @@ * @author Joseph D. Darcy * * @compile/fail/ref=FauxEnum3.out -XDrawDiagnostics FauxEnum3.java - * @compile/fail/ref=FauxEnum3.out -XDrawDiagnostics --enable-preview -source ${jdk.version} FauxEnum3.java */ public final class FauxEnum3 extends SpecializedEnum {} diff --git a/test/langtools/tools/javac/enum/FauxEnum3.out b/test/langtools/tools/javac/enum/FauxEnum3.out index aaf4855e215..885154d073a 100644 --- a/test/langtools/tools/javac/enum/FauxEnum3.out +++ b/test/langtools/tools/javac/enum/FauxEnum3.out @@ -1,2 +1,2 @@ -FauxEnum3.java:11:14: compiler.err.enum.types.not.extensible -1 error \ No newline at end of file +FauxEnum3.java:10:14: compiler.err.enum.types.not.extensible +1 error diff --git a/test/langtools/tools/javac/enum/LocalEnum.java b/test/langtools/tools/javac/enum/LocalEnum.java index 0cbb0bf438c..331992b3565 100644 --- a/test/langtools/tools/javac/enum/LocalEnum.java +++ b/test/langtools/tools/javac/enum/LocalEnum.java @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ - * @bug 5019609 + * @bug 5019609 8246774 * @summary javac fails to reject local enums * @author gafter - * @compile/fail/ref=LocalEnum.out -XDrawDiagnostics LocalEnum.java - * @compile --enable-preview -source ${jdk.version} LocalEnum.java + * @compile/fail/ref=LocalEnum.out -XDrawDiagnostics -source 15 LocalEnum.java + * @compile LocalEnum.java */ public class LocalEnum { diff --git a/test/langtools/tools/javac/enum/LocalEnum.out b/test/langtools/tools/javac/enum/LocalEnum.out index ee4cc2d10f5..a01b8555456 100644 --- a/test/langtools/tools/javac/enum/LocalEnum.out +++ b/test/langtools/tools/javac/enum/LocalEnum.out @@ -1,2 +1,4 @@ +- compiler.warn.source.no.system.modules.path: 15 LocalEnum.java:12:9: compiler.err.local.enum 1 error +1 warning diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java index 76082210850..1f622e0fefc 100644 --- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8192920 8204588 + * @bug 8192920 8204588 8246774 * @summary Test source launcher * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -299,7 +299,7 @@ public void testHelloWorldWithShebangJava(Path base) throws IOException { file + ":1: error: illegal character: '#'\n" + "#!/usr/bin/java --source " + thisVersion + "\n" + "^\n" + - file + ":1: error: class, interface, or enum expected\n" + + file + ":1: error: class, interface, enum, or record expected\n" + "#!/usr/bin/java --source " + thisVersion + "\n" + " ^\n" + "2 errors\n", @@ -505,7 +505,7 @@ public void testBadShebang(Path base) throws IOException { file + ":1: error: illegal character: '#'\n" + "#/usr/bin/java --source " + thisVersion + "\n" + "^\n" + - file + ":1: error: class, interface, or enum expected\n" + + file + ":1: error: class, interface, enum, or record expected\n" + "#/usr/bin/java --source " + thisVersion + "\n" + " ^\n" + "2 errors\n", diff --git a/test/langtools/tools/javac/parser/JavacParserTest.java b/test/langtools/tools/javac/parser/JavacParserTest.java index cb7b8d01382..e12e40ce4c4 100644 --- a/test/langtools/tools/javac/parser/JavacParserTest.java +++ b/test/langtools/tools/javac/parser/JavacParserTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 + * @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 * @summary tests error and diagnostics positions * @author Jan Lahoda * @modules jdk.compiler/com.sun.tools.javac.api @@ -999,7 +999,7 @@ void testVoidLambdaParameter() throws IOException { @Test //JDK-8065753 void testWrongFirstToken() throws IOException { String code = "<"; - String expectedErrors = "Test.java:1:1: compiler.err.expected3: class, interface, enum\n" + + String expectedErrors = "Test.java:1:1: compiler.err.expected4: class, interface, enum, record\n" + "1 error\n"; StringWriter out = new StringWriter(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(out, fm, null, diff --git a/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out b/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out index 8c8f0566d15..3748ccfeb97 100644 --- a/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out +++ b/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out @@ -1,3 +1,3 @@ SingleCommaAnnotationValueFail.java:34:12: compiler.err.expected: '}' -SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected3: class, interface, enum +SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected4: class, interface, enum, record 2 errors diff --git a/test/langtools/tools/javac/processing/model/element/JavaxLangModelForRecords.java b/test/langtools/tools/javac/processing/model/element/JavaxLangModelForRecords.java index 85fa3b90435..9bc06ce6d42 100644 --- a/test/langtools/tools/javac/processing/model/element/JavaxLangModelForRecords.java +++ b/test/langtools/tools/javac/processing/model/element/JavaxLangModelForRecords.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8246774 * @summary Verify that annotation processing works for records * @library /tools/lib /tools/javac/lib * @modules @@ -67,7 +68,6 @@ public class JavaxLangModelForRecords extends TestRunner { } public static void main(String... args) throws Exception { - System.out.println(System.getProperties()); new JavaxLangModelForRecords().runTests(); } @@ -105,17 +105,13 @@ public void testQualifiedClassForProcessing(Path base) throws Exception { tb.writeJavaFiles(r, "record R(int i) {}"); - List expected = List.of("Note: field: i", - "Note: record component: i", - "Note: testQualifiedClassForProcessing" + File.separator + "src" + File.separator - + "R" + File.separator + "R.java uses preview language features.", - "Note: Recompile with -Xlint:preview for details."); + List expected = List.of( + "Note: field: i", + "Note: record component: i"); for (Mode mode : new Mode[] {Mode.API}) { List log = new JavacTask(tb, mode) - .options("-processor", QualifiedClassForProcessing.class.getName(), - "--enable-preview", - "-source", Integer.toString(Runtime.version().feature())) + .options("-processor", QualifiedClassForProcessing.class.getName()) .files(findJavaFiles(src)) .outdir(classes) .run() diff --git a/test/langtools/tools/javac/records/ElementFilterRecordComponentTest.java b/test/langtools/tools/javac/records/ElementFilterRecordComponentTest.java index 062de5b5392..3ca306ed34f 100644 --- a/test/langtools/tools/javac/records/ElementFilterRecordComponentTest.java +++ b/test/langtools/tools/javac/records/ElementFilterRecordComponentTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8241312 + * @bug 8241312 8246774 * @summary test for javax.lang.model.util.ElementFilter::recordComponentsIn * @modules jdk.compiler/com.sun.tools.javac.util */ @@ -47,8 +47,7 @@ public class ElementFilterRecordComponentTest { public static void main(String... args) throws IOException { JavaCompiler c = ToolProvider.getSystemJavaCompiler(); - JavacTask t = (JavacTask) c.getTask(null, null, null, - List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())), null, + JavacTask t = (JavacTask) c.getTask(null, null, null, null, null, List.of(new SimpleJavaFileObject(URI.create("TestClass.java"), JavaFileObject.Kind.SOURCE) { @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { diff --git a/test/langtools/tools/javac/records/LocalStaticDeclarations.java b/test/langtools/tools/javac/records/LocalStaticDeclarations.java index 1b8519bc7b9..53dd9854231 100644 --- a/test/langtools/tools/javac/records/LocalStaticDeclarations.java +++ b/test/langtools/tools/javac/records/LocalStaticDeclarations.java @@ -23,15 +23,14 @@ /* * @test - * @bug 8242293 + * @bug 8242293 8246774 * @summary allow for local interfaces and enums plus nested records, interfaces and enums * @library /tools/javac/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file * jdk.compiler/com.sun.tools.javac.util * @build combo.ComboTestHelper - * @compile --enable-preview -source ${jdk.version} LocalStaticDeclarations.java - * @run main/othervm --enable-preview LocalStaticDeclarations + * @run main LocalStaticDeclarations */ import javax.lang.model.element.Element; @@ -175,7 +174,6 @@ public static void main(String... args) throws Exception { @Override public void doWork() throws Throwable { newCompilationTask() - .withOptions(new String[]{"--enable-preview", "-source", Integer.toString(Runtime.version().feature())}) .withSourceFromTemplate("Test", sourceTemplate) .generate(this::check); } diff --git a/test/langtools/tools/javac/records/MapAccessorToComponent.java b/test/langtools/tools/javac/records/MapAccessorToComponent.java index e8f2bcac492..9927d0ddb76 100644 --- a/test/langtools/tools/javac/records/MapAccessorToComponent.java +++ b/test/langtools/tools/javac/records/MapAccessorToComponent.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8246774 * @summary test for javax.lang.model.util.Elements::recordComponentFor * @modules jdk.compiler */ @@ -51,8 +52,7 @@ public static void main(String... args) throws IOException { public void run() throws IOException { String code = "record R(int val1, int val2) {}"; JavaCompiler c = ToolProvider.getSystemJavaCompiler(); - JavacTask t = (JavacTask) c.getTask(null, null, null, - List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())), null, + JavacTask t = (JavacTask) c.getTask(null, null, null, null, null, List.of(new MyFileObject(code))); TypeElement record = (TypeElement) t.analyze().iterator().next(); for (RecordComponentElement rce : ElementFilter.recordComponentsIn(record.getEnclosedElements())) { diff --git a/test/langtools/tools/javac/records/RecordCompilationTests.java b/test/langtools/tools/javac/records/RecordCompilationTests.java index 279ded7443d..ee9c99a8e7b 100644 --- a/test/langtools/tools/javac/records/RecordCompilationTests.java +++ b/test/langtools/tools/javac/records/RecordCompilationTests.java @@ -26,7 +26,8 @@ /** * RecordCompilationTests * - * @test 8250629 8252307 8247352 8241151 + * @test + * @bug 8250629 8252307 8247352 8241151 8246774 * @summary Negative compilation tests, and positive compilation (smoke) tests for records * @library /lib/combo /tools/lib /tools/javac/lib * @modules @@ -35,9 +36,8 @@ * jdk.compiler/com.sun.tools.javac.util * jdk.jdeps/com.sun.tools.classfile * @build JavacTestingAbstractProcessor - * @compile --enable-preview -source ${jdk.version} RecordCompilationTests.java - * @run testng/othervm -DuseAP=false --enable-preview RecordCompilationTests - * @run testng/othervm -DuseAP=true --enable-preview RecordCompilationTests + * @run testng/othervm -DuseAP=false RecordCompilationTests + * @run testng/othervm -DuseAP=true RecordCompilationTests */ import java.io.File; @@ -119,17 +119,7 @@ @Test public class RecordCompilationTests extends CompilationTestCase { - // @@@ When records become a permanent feature, we don't need these any more - private static String[] PREVIEW_OPTIONS = { - "--enable-preview", - "-source", Integer.toString(Runtime.version().feature()) - }; - - private static String[] PREVIEW_OPTIONS_WITH_AP = { - "--enable-preview", - "-source", Integer.toString(Runtime.version().feature()), - "-processor", SimplestAP.class.getName() - }; + private static String[] OPTIONS_WITH_AP = {"-processor", SimplestAP.class.getName()}; private static final List BAD_COMPONENT_NAMES = List.of( "clone", "finalize", "getClass", "hashCode", @@ -150,7 +140,9 @@ public boolean process(Set annotations, RoundEnvironment public RecordCompilationTests() { useAP = System.getProperty("useAP", "false").equals("true"); setDefaultFilename("R.java"); - setCompileOptions(useAP ? PREVIEW_OPTIONS_WITH_AP : PREVIEW_OPTIONS); + if (useAP) { + setCompileOptions(OPTIONS_WITH_AP); + } System.out.println(useAP ? "running all tests using an annotation processor" : "running all tests without annotation processor"); } @@ -1010,7 +1002,7 @@ public void testAcceptRecordId() { String[] previousOptions = getCompileOptions(); String[] testOptions = {/* no options */}; setCompileOptions(testOptions); - assertOKWithWarning("compiler.warn.restricted.type.not.allowed.preview", + assertFail("compiler.err.illegal.start.of.type", "class R {\n" + " record RR(int i) {\n" + " return null;\n" + @@ -1062,8 +1054,6 @@ record R(@Anno String s) {} ); String[] generalOptions = { - "--enable-preview", - "-source", Integer.toString(Runtime.version().feature()), "-processor", Processor.class.getName(), "-Atargets=" }; diff --git a/test/langtools/tools/javac/records/RecordMemberTests.java b/test/langtools/tools/javac/records/RecordMemberTests.java index 85d9434ffb6..a754f294723 100644 --- a/test/langtools/tools/javac/records/RecordMemberTests.java +++ b/test/langtools/tools/javac/records/RecordMemberTests.java @@ -24,11 +24,10 @@ */ /** - * RecordMemberTests - * * @test - * @compile --enable-preview -source ${jdk.version} RecordMemberTests.java - * @run testng/othervm --enable-preview RecordMemberTests + * @bug 8246774 + * @summary test several assertions on record classes members + * @run testng RecordMemberTests */ import java.lang.reflect.Constructor; diff --git a/test/langtools/tools/javac/records/VarargsRecordsTest.java b/test/langtools/tools/javac/records/VarargsRecordsTest.java index 2151db278ac..2e60ec810ea 100644 --- a/test/langtools/tools/javac/records/VarargsRecordsTest.java +++ b/test/langtools/tools/javac/records/VarargsRecordsTest.java @@ -33,11 +33,10 @@ import static org.testng.Assert.*; /** - * VarargsRecordsTest - * * @test - * @compile --enable-preview -source ${jdk.version} VarargsRecordsTest.java - * @run testng/othervm --enable-preview VarargsRecordsTest + * @bug 8246774 + * @summary test for varargs record components + * @run testng VarargsRecordsTest */ @Test public class VarargsRecordsTest { diff --git a/test/langtools/tools/javac/records/mandated_members/CheckRecordMembers.java b/test/langtools/tools/javac/records/mandated_members/CheckRecordMembers.java index e862ec42538..f0aab5985d5 100644 --- a/test/langtools/tools/javac/records/mandated_members/CheckRecordMembers.java +++ b/test/langtools/tools/javac/records/mandated_members/CheckRecordMembers.java @@ -25,6 +25,7 @@ * CheckRecordMembers * * @test + * @bug 8246774 * @summary check that the accessors, equals, hashCode and toString methods * work as expected * @library /tools/javac/lib @@ -32,7 +33,7 @@ * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.util * @build combo.ComboTestHelper - * @run main/othervm --enable-preview CheckRecordMembers + * @run main CheckRecordMembers */ import java.lang.reflect.Constructor; @@ -102,7 +103,6 @@ public static void main(String... args) throws Exception { @Override public void doWork() throws Throwable { newCompilationTask() - .withOptions(new String[]{"--enable-preview", "-source", Integer.toString(Runtime.version().feature())}) .withSourceFromTemplate("Data", sourceTemplate) .generate(this::check); } diff --git a/test/langtools/tools/javac/records/writeread/WriteReadTest.java b/test/langtools/tools/javac/records/writeread/WriteReadTest.java index 2d6430ee7ae..e7d75a852f4 100644 --- a/test/langtools/tools/javac/records/writeread/WriteReadTest.java +++ b/test/langtools/tools/javac/records/writeread/WriteReadTest.java @@ -23,9 +23,10 @@ /* * @test + * @bug 8246774 * @summary Verify javac can read record classfiles it writes - * @compile --enable-preview -source ${jdk.version} Record.java - * @compile --enable-preview -source ${jdk.version} WriteReadTest.java + * @compile Record.java + * @compile WriteReadTest.java */ public class WriteReadTest { Record1 r1; diff --git a/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.java b/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.java index ff48ef133b5..a796411fc66 100644 --- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.java +++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8206986 + * @bug 8206986 8254286 * @summary Check types inferred for switch expressions. * @compile/fail/ref=ExpressionSwitchInfer.out -XDrawDiagnostics ExpressionSwitchInfer.java */ @@ -34,4 +34,53 @@ private T test(List l, Class c, String param) { return null; } + void bug8254286(I1 i1, I2 i2, int s) { + var t1 = switch (s) { + case 1 -> i1; + case 2 -> null; + default -> i2; + }; + t1.m(); + var t2 = switch (s) { + case 2 -> null; + case 1 -> i1; + default -> i2; + }; + t2.m(); + var t3 = switch (s) { + case 1 -> i1; + default -> i2; + case 2 -> null; + }; + t3.m(); + var t4 = switch (s) { + case 1 -> i1; + default -> null; + }; + t4.m(); + var t5 = switch (s) { + default -> null; + case 1 -> i1; + }; + t5.m(); + var t6 = switch (s) { + default -> null; + }; + var t7 = switch (s) { + case 1 -> null; + default -> null; + }; + var t8 = switch (s) { + case 1 -> null; + case 2 -> null; + default -> null; + }; + } + + interface I { + void m(); + } + interface I1 extends I {} + interface I2 extends I {} + } diff --git a/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.out b/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.out index b0b4a738c9c..5359db37da3 100644 --- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.out +++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchInfer.out @@ -1,4 +1,7 @@ ExpressionSwitchInfer.java:17:95: compiler.err.cant.resolve.location.args: kindname.method, substring, , int, (compiler.misc.location: kindname.interface, java.lang.CharSequence, null) ExpressionSwitchInfer.java:26:38: compiler.err.cant.resolve.location.args: kindname.method, substring, , int, (compiler.misc.location: kindname.interface, java.lang.CharSequence, null) ExpressionSwitchInfer.java:30:23: compiler.err.prob.found.req: (compiler.misc.incompatible.type.in.switch.expression: (compiler.misc.inconvertible.types: int, java.lang.String)) -3 errors +ExpressionSwitchInfer.java:66:13: compiler.err.cant.infer.local.var.type: t6, (compiler.misc.local.cant.infer.null) +ExpressionSwitchInfer.java:69:13: compiler.err.cant.infer.local.var.type: t7, (compiler.misc.local.cant.infer.null) +ExpressionSwitchInfer.java:73:13: compiler.err.cant.infer.local.var.type: t8, (compiler.misc.local.cant.infer.null) +6 errors diff --git a/test/langtools/tools/javac/tree/TreePosTest.java b/test/langtools/tools/javac/tree/TreePosTest.java index ba5876bb9d9..add1db72e29 100644 --- a/test/langtools/tools/javac/tree/TreePosTest.java +++ b/test/langtools/tools/javac/tree/TreePosTest.java @@ -79,6 +79,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeInfo; @@ -419,6 +420,14 @@ private boolean isAnnotatedArray(JCTree tree) { ((JCAnnotatedType)tree).underlyingType.hasTag(TYPEARRAY); } + @Override + public void visitMethodDef(JCMethodDecl tree) { + // ignore compact record constructors + if ((tree.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) == 0) { + super.visitMethodDef(tree); + } + } + @Override public void visitVarDef(JCVariableDecl tree) { // enum member declarations are desugared in the parser and have diff --git a/test/langtools/tools/sjavac/PubApisTest.java b/test/langtools/tools/sjavac/PubApisTest.java index 2192aeee531..c62166fb793 100644 --- a/test/langtools/tools/sjavac/PubApisTest.java +++ b/test/langtools/tools/sjavac/PubApisTest.java @@ -23,13 +23,12 @@ /* * @test - * @bug 8241312 + * @bug 8241312 8246774 * @summary test for com.sun.tools.sjavac.comp.PubAPIs and com.sun.tools.sjavac.comp.PubapiVisitor * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.util * jdk.compiler/com.sun.tools.sjavac.comp * jdk.compiler/com.sun.tools.sjavac.pubapi - * @run main PubApisTest */ import com.sun.source.util.JavacTask; import com.sun.tools.javac.util.Context; @@ -48,8 +47,7 @@ public class PubApisTest { public static void main(String[] args) throws Throwable { javax.tools.JavaCompiler c = ToolProvider.getSystemJavaCompiler(); - JavacTask t = (JavacTask) c.getTask(null, null, null, - List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())), null, + JavacTask t = (JavacTask) c.getTask(null, null, null, null, null, List.of(new SimpleJavaFileObject(URI.create("TestClass.java"), JavaFileObject.Kind.SOURCE) { @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { diff --git a/test/lib-test/jdk/test/lib/hexdump/ASN1FormatterTest.java b/test/lib-test/jdk/test/lib/hexdump/ASN1FormatterTest.java index 01887fa8baa..c7622d4b9b4 100644 --- a/test/lib-test/jdk/test/lib/hexdump/ASN1FormatterTest.java +++ b/test/lib-test/jdk/test/lib/hexdump/ASN1FormatterTest.java @@ -39,6 +39,7 @@ /* * @test * @summary ASN.1 formatting + * @modules java.base/sun.security.util * @library /test/lib * @compile ASN1FormatterTest.java * @run testng jdk.test.lib.hexdump.ASN1FormatterTest diff --git a/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java b/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java index 17484d89d52..f3c2179191f 100644 --- a/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java +++ b/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java @@ -14,14 +14,22 @@ public ArtifactResolverException(String message, Throwable cause) { } public String toString() { - return super.toString() + ": " + getRootCause().toString(); + Throwable root = getRootCause(); + if (root != null) { + return super.toString() + ": " + root.toString(); + } else { + return super.toString(); + } } public Throwable getRootCause() { - Throwable rootCause = getCause(); - while (rootCause.getCause() != null && rootCause.getCause() != rootCause) { - rootCause = rootCause.getCause(); + Throwable root = getCause(); + if (root == null) { + return null; + } + while (root.getCause() != null && root.getCause() != root) { + root = root.getCause(); } - return rootCause; + return root; } } diff --git a/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java b/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java index fb9486c3f95..086aa81e471 100644 --- a/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java +++ b/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java @@ -412,7 +412,6 @@ private static String oidName(byte[] bytes) { // Look up the OID; if the class is not accessible just return the numeric form Class cl = Class.forName("sun.security.util.KnownOIDs"); Method findMatch = cl.getDeclaredMethod("findMatch", String.class); - findMatch.setAccessible(true); Object oid = findMatch.invoke(null, noid); return (oid == null) ? noid : noid + " (" + oid.toString() + ")"; } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { diff --git a/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java b/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java index b2dbefe3c05..f119ce37b2b 100644 --- a/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java +++ b/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java @@ -82,7 +82,7 @@ @Measurement(iterations = 10, time = 1) @OutputTimeUnit(TimeUnit.MICROSECONDS) @State(Scope.Thread) -@Fork(value = 1, warmups = 0, jvmArgsAppend = "--enable-preview") +@Fork(value = 1, warmups = 0) public class RecordDeserialization { public record PointR(int x, int y) implements Serializable {} diff --git a/test/micro/org/openjdk/bench/java/lang/StringIndexOfChar.java b/test/micro/org/openjdk/bench/java/lang/StringIndexOfChar.java index 245789ae10a..adc3c296460 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringIndexOfChar.java +++ b/test/micro/org/openjdk/bench/java/lang/StringIndexOfChar.java @@ -25,10 +25,13 @@ import java.util.Random; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; import java.util.concurrent.TimeUnit; @@ -41,18 +44,37 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) public class StringIndexOfChar { - private static final int loops = 100000; - private static final Random rng = new Random(1999); - private static final int pathCnt = 1000; - private static final String [] latn1_short = new String[pathCnt]; - private static final String [] latn1_sse4 = new String[pathCnt]; - private static final String [] latn1_avx2 = new String[pathCnt]; - private static final String [] latn1_mixedLength = new String[pathCnt]; - private static final String [] utf16_short = new String[pathCnt]; - private static final String [] utf16_sse4 = new String[pathCnt]; - private static final String [] utf16_avx2 = new String[pathCnt]; - private static final String [] utf16_mixedLength = new String[pathCnt]; - static { + @Param("100000") + private int loops; + + @Param("1000") + private int pathCnt; + + @Param("1999") + private int rngSeed; + + private Random rng; + private String[] latn1_short; + private String[] latn1_sse4; + private String[] latn1_avx2; + private String[] latn1_mixedLength; + private String[] utf16_short; + private String[] utf16_sse4; + private String[] utf16_avx2; + private String[] utf16_mixedLength; + + @Setup + public void setup() { + rng = new Random(rngSeed); + latn1_short = new String[pathCnt]; + latn1_sse4 = new String[pathCnt]; + latn1_avx2 = new String[pathCnt]; + latn1_mixedLength = new String[pathCnt]; + utf16_short = new String[pathCnt]; + utf16_sse4 = new String[pathCnt]; + utf16_avx2 = new String[pathCnt]; + utf16_mixedLength = new String[pathCnt]; + for (int i = 0; i < pathCnt; i++) { latn1_short[i] = makeRndString(false, 15); latn1_sse4[i] = makeRndString(false, 16); @@ -65,7 +87,7 @@ public class StringIndexOfChar { } } - private static String makeRndString(boolean isUtf16, int length) { + private String makeRndString(boolean isUtf16, int length) { StringBuilder sb = new StringBuilder(length); if(length > 0){ sb.append(isUtf16?'\u2026':'b'); // ... @@ -81,141 +103,116 @@ private static String makeRndString(boolean isUtf16, int length) { @Benchmark - public void latin1_mixed_char() { - int ret = 0; + public void latin1_mixed_char(Blackhole bh) { for (String what : latn1_mixedLength) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } } @Benchmark - public void utf16_mixed_char() { - int ret = 0; + public void utf16_mixed_char(Blackhole bh) { for (String what : utf16_mixedLength) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } } @Benchmark - public void latin1_mixed_String() { - int ret = 0; + public void latin1_mixed_String(Blackhole bh) { for (String what : latn1_mixedLength) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } } @Benchmark - public void utf16_mixed_String() { - int ret = 0; + public void utf16_mixed_String(Blackhole bh) { for (String what : utf16_mixedLength) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } } ////////// more detailed code path dependent tests ////////// @Benchmark - public void latin1_Short_char() { - int ret = 0; + public void latin1_Short_char(Blackhole bh) { for (String what : latn1_short) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } } @Benchmark - public void latin1_SSE4_char() { - int ret = 0; + public void latin1_SSE4_char(Blackhole bh) { for (String what : latn1_sse4) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } } @Benchmark - public void latin1_AVX2_char() { - int ret = 0; + public void latin1_AVX2_char(Blackhole bh) { for (String what : latn1_avx2) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } } @Benchmark - public int utf16_Short_char() { - int ret = 0; + public void utf16_Short_char(Blackhole bh) { for (String what : utf16_short) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } - return ret; } @Benchmark - public int utf16_SSE4_char() { - int ret = 0; + public void utf16_SSE4_char(Blackhole bh) { for (String what : utf16_sse4) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } - return ret; } @Benchmark - public int utf16_AVX2_char() { - int ret = 0; + public void utf16_AVX2_char(Blackhole bh) { for (String what : utf16_avx2) { - ret += what.indexOf('a'); + bh.consume(what.indexOf('a')); } - return ret; } @Benchmark - public int latin1_Short_String() { - int ret = 0; + public void latin1_Short_String(Blackhole bh) { for (String what : latn1_short) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } @Benchmark - public int latin1_SSE4_String() { - int ret = 0; + public void latin1_SSE4_String(Blackhole bh) { for (String what : latn1_sse4) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } @Benchmark - public int latin1_AVX2_String() { - int ret = 0; + public void latin1_AVX2_String(Blackhole bh) { for (String what : latn1_avx2) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } @Benchmark - public int utf16_Short_String() { - int ret = 0; + public void utf16_Short_String(Blackhole bh) { for (String what : utf16_short) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } @Benchmark - public int utf16_SSE4_String() { - int ret = 0; + public void utf16_SSE4_String(Blackhole bh) { for (String what : utf16_sse4) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } @Benchmark - public int utf16_AVX2_String() { - int ret = 0; + public void utf16_AVX2_String(Blackhole bh) { for (String what : utf16_avx2) { - ret += what.indexOf("a"); + bh.consume(what.indexOf("a")); } - return ret; } } diff --git a/test/micro/org/openjdk/bench/java/math/BigIntegers.java b/test/micro/org/openjdk/bench/java/math/BigIntegers.java index 8b26b47cf1c..d3a20a3ee5e 100644 --- a/test/micro/org/openjdk/bench/java/math/BigIntegers.java +++ b/test/micro/org/openjdk/bench/java/math/BigIntegers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.infra.Blackhole; import java.math.BigInteger; @@ -45,11 +46,14 @@ @State(Scope.Thread) public class BigIntegers { - private BigInteger[] hugeArray, largeArray, smallArray, shiftArray; + private BigInteger[] hugeArray, largeArray, smallArray, shiftArray, smallShiftArray; public String[] dummyStringArray; public Object[] dummyArr; private static final int TESTSIZE = 1000; + @Param({"32", "64", "96", "128", "160", "192", "224", "256"}) + private int maxNumbits; + @Setup public void setup() { Random r = new Random(1123); @@ -72,6 +76,9 @@ public void setup() { * Each array entry is atmost 16k bits * in size */ + smallShiftArray = new BigInteger[TESTSIZE]; /* + * Small numbers, bits count in range [maxNumbits - 31, maxNumbits] + */ dummyStringArray = new String[TESTSIZE]; dummyArr = new Object[TESTSIZE]; @@ -84,6 +91,7 @@ public void setup() { largeArray[i] = new BigInteger("" + ((long) value + (long) Integer.MAX_VALUE)); smallArray[i] = new BigInteger("" + ((long) value / 1000)); shiftArray[i] = new BigInteger(numbits, r); + smallShiftArray[i] = new BigInteger(Math.max(maxNumbits - value % 32, 0), r); } } @@ -177,4 +185,30 @@ public void testRightShift(Blackhole bh) { } bh.consume(tmp); } + + /** Invokes the shiftLeft method of small BigInteger with different values. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testSmallLeftShift(Blackhole bh) { + Random rand = new Random(); + int shift = rand.nextInt(30) + 1; + BigInteger tmp = null; + for (BigInteger s : smallShiftArray) { + tmp = s.shiftLeft(shift); + bh.consume(tmp); + } + } + + /** Invokes the shiftRight method of small BigInteger with different values. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testSmallRightShift(Blackhole bh) { + Random rand = new Random(); + int shift = rand.nextInt(30) + 1; + BigInteger tmp = null; + for (BigInteger s : smallShiftArray) { + tmp = s.shiftRight(shift); + bh.consume(tmp); + } + } } diff --git a/test/micro/org/openjdk/bench/java/net/SocketChannelCompare.java b/test/micro/org/openjdk/bench/java/net/SocketChannelCompare.java new file mode 100644 index 00000000000..2d67bed5f23 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/SocketChannelCompare.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Tests sending a 128 byte message on a second, to a thread which + * echo's it back and received by the original thread. + * Benchmark is performed for "inet" channels over TCP/IP + * and "unix" domain channels. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class SocketChannelCompare { + + static final int BUFSIZE = 128; // message size sent and received + private ServerSocketChannel ssc; + private SocketChannel s1, s2; + private EchoThread rt; + private ByteBuffer bb = ByteBuffer.allocate(BUFSIZE); + + private static volatile String tempDir; + private static final AtomicInteger count = new AtomicInteger(0); + private volatile Path socket; + + @Param({"inet", "unix"}) + private volatile String family; + + static { + try { + Path p = Files.createTempDirectory("readWriteTest"); + tempDir = p.toString(); + } catch (IOException e) { + tempDir = null; + } + } + + private ServerSocketChannel getServerSocketChannel() throws IOException { + if (family.equals("inet")) + return getInetServerSocketChannel(); + else if (family.equals("unix")) + return getUnixServerSocketChannel(); + throw new InternalError(); + } + + + private ServerSocketChannel getInetServerSocketChannel() throws IOException { + InetAddress iaddr = InetAddress.getLoopbackAddress(); + return ServerSocketChannel.open().bind(null); + } + + private ServerSocketChannel getUnixServerSocketChannel() throws IOException { + int next = count.incrementAndGet(); + socket = Paths.get(tempDir, Integer.toString(next)); + UnixDomainSocketAddress addr = UnixDomainSocketAddress.of(socket); + return ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(addr); + } + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + ssc = getServerSocketChannel(); + s1 = SocketChannel.open(ssc.getLocalAddress()); + s2 = ssc.accept(); + + rt = new EchoThread(s2); + rt.start(); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException, InterruptedException { + s1.close(); + s2.close(); + ssc.close(); + if (family.equals("unix")) { + Files.delete(socket); + Files.delete(Path.of(tempDir)); + } + rt.join(); + } + + @Benchmark + public void test() throws IOException { + bb.position(0).limit(BUFSIZE); + s1.write(bb); + bb.clear(); + readFully(s1, bb); + } + + // read until buf is full, or EOF. Always returns number of bytes read + + static int readFully(SocketChannel chan, ByteBuffer buf) throws IOException { + int n = buf.remaining(); + int count = 0; + while (n > 0) { + int c = chan.read(buf); + if (c == -1) + return count; + n -= c; + count += c; + } + return count; + } + + static class EchoThread extends Thread { + private SocketChannel sc; + + public EchoThread(SocketChannel s2) { + this.sc = s2; + } + + public void run() { + try { + ByteBuffer bb = ByteBuffer.allocate(BUFSIZE); + while (true) { + bb.clear(); + int c = readFully(sc, bb); + if (c == 0) { + sc.close(); + return; + } + bb.flip(); + sc.write(bb); + } + } catch (ClosedChannelException ex) { + // shutdown time + } catch (IOException ioex) { + ioex.printStackTrace(); + } + } + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(org.openjdk.bench.java.net.SocketChannelCompare.class.getSimpleName()) + .warmupForks(1) + .warmupIterations(2) + .measurementIterations(2) + .forks(2) + .build(); + + new Runner(opt).run(); + + opt = new OptionsBuilder() + .include(org.openjdk.bench.java.net.SocketChannelCompare.class.getSimpleName()) + .warmupForks(1) + .warmupIterations(2) + .measurementIterations(2) + .jvmArgsPrepend("-Djdk.net.useFastTcpLoopback=true") + .forks(3) + .build(); + + new Runner(opt).run(); + } +} diff --git a/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java b/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java new file mode 100644 index 00000000000..965c8d41c79 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Measures connection setup times + */ +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class SocketChannelConnectionSetup { + + private ServerSocketChannel ssc; + private SocketChannel s1, s2; + + private static volatile String tempDir; + private static final AtomicInteger count = new AtomicInteger(0); + private volatile Path socket; + + @Param({"inet", "unix"}) + private volatile String family; + + static { + try { + Path p = Files.createTempDirectory("readWriteTest"); + tempDir = p.toString(); + } catch (IOException e) { + tempDir = null; + } + } + + private ServerSocketChannel getServerSocketChannel() throws IOException { + if (family.equals("inet")) + return getInetServerSocketChannel(); + else if (family.equals("unix")) + return getUnixServerSocketChannel(); + throw new InternalError(); + } + + + private ServerSocketChannel getInetServerSocketChannel() throws IOException { + InetAddress iaddr = InetAddress.getLoopbackAddress(); + return ServerSocketChannel.open().bind(null); + } + + private ServerSocketChannel getUnixServerSocketChannel() throws IOException { + int next = count.incrementAndGet(); + socket = Paths.get(tempDir, Integer.toString(next)); + UnixDomainSocketAddress addr = UnixDomainSocketAddress.of(socket); + return ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(addr); + } + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + ssc = getServerSocketChannel(); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException, InterruptedException { + ssc.close(); + if (family.equals("unix")) { + Files.delete(socket); + Files.delete(Path.of(tempDir)); + } + } + + @Benchmark + @Measurement(iterations = 5, batchSize=200) + public void test() throws IOException { + s1 = SocketChannel.open(ssc.getLocalAddress()); + s2 = ssc.accept(); + s1.close(); + s2.close(); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(org.openjdk.bench.java.net.SocketChannelConnectionSetup.class.getSimpleName()) + .warmupForks(1) + .forks(2) + .build(); + + new Runner(opt).run(); + + opt = new OptionsBuilder() + .include(org.openjdk.bench.java.net.SocketChannelConnectionSetup.class.getSimpleName()) + .jvmArgsPrepend("-Djdk.net.useFastTcpLoopback=true") + .warmupForks(1) + .forks(2) + .build(); + + new Runner(opt).run(); + } +} diff --git a/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java b/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java new file mode 100644 index 00000000000..9e75b0d556c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import java.io.IOException; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on network conditions and paltform. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class UnixSocketChannelReadWrite { + + private ServerSocketChannel ssc; + private SocketChannel s1, s2; + private ReadThread rt; + private ByteBuffer bb = ByteBuffer.allocate(1); + + private static volatile String tempDir; + private static final AtomicInteger count = new AtomicInteger(0); + private volatile Path socket; + + static { + try { + Path p = Files.createTempDirectory("readWriteTest"); + tempDir = p.toString(); + } catch (IOException e) { + tempDir = null; + } + } + + private ServerSocketChannel getServerSocketChannel() throws IOException { + int next = count.incrementAndGet(); + socket = Paths.get(tempDir, Integer.toString(next)); + UnixDomainSocketAddress addr = UnixDomainSocketAddress.of(socket); + ServerSocketChannel c = ServerSocketChannel.open(StandardProtocolFamily.UNIX); + c.bind(addr); + return c; + } + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + ssc = getServerSocketChannel(); + s1 = SocketChannel.open(ssc.getLocalAddress()); + s2 = ssc.accept(); + + rt = new ReadThread(s2); + rt.start(); + + bb.put((byte) 47); + bb.flip(); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException, InterruptedException { + s1.close(); + s2.close(); + ssc.close(); + Files.delete(socket); + Files.delete(Path.of(tempDir)); + rt.join(); + } + + @Benchmark + public void test() throws IOException { + s1.write(bb); + bb.flip(); + } + + static class ReadThread extends Thread { + private SocketChannel sc; + + public ReadThread(SocketChannel s2) { + this.sc = s2; + } + + public void run() { + try { + ByteBuffer bb = ByteBuffer.allocate(1); + while (sc.read(bb) > 0) { + bb.flip(); + } + } catch (ClosedChannelException ex) { + // shutdown time + } catch (IOException e) { + e.printStackTrace(); + } + } + } + +}